#if (FEATURE_MODE == 0)
/**
 @file sys_usw_stacking.c

 @date 2010-3-9

 @version v2.0

  This file contains stakcing sys layer function implementation
*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "ctc_stacking.h"
#include "ctc_vector.h"
#include "ctc_linklist.h"
#include "ctc_error.h"
#include "ctc_warmboot.h"

#include "sys_usw_common.h"
#include "sys_usw_opf.h"
#include "sys_usw_ftm.h"
#include "sys_usw_register.h"
#include "sys_usw_port_api.h"
#include "sys_usw_packet.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_stacking.h"
#include "sys_usw_dma.h"

#include "drv_api.h"

/****************************************************************************
*
* Defines and Macros
*
*****************************************************************************/

#define SYS_STK_TRUNK_MIN_ID (DRV_IS_TMG(lchip)?0:1)

#define SYS_STK_TRUNK_VEC_BLOCK_NUM  128
#define SYS_STK_TRUNK_VEC_BLOCK_SIZE 8

#define SYS_STK_KEEPLIVE_VEC_BLOCK_SIZE 1024
#define SYS_STK_KEEPLIVE_MEM_MAX 3

#define SYS_STK_MCAST_PROFILE_MAX 16384

#define SYS_STK_MAX_GCHIP     128
#define SYS_STK_PORT_BLOCK_PROFILE_NUM 8
#define SYS_STK_PORT_FWD_PROFILE_NUM 8
#define SYS_STK_MAX_PORT_CNT  128

#define SYS_STACKING_BLOCK_PORT_UINT 64
#define SYS_STACKING_MAX_DLB_FLOW_NUM 8192

#define SYS_STACKING_SRC_PORT_MODE_PORT_GCHIP       0
#define SYS_STACKING_SRC_PORT_MODE_TRUNK_ID_GCHIP   1
#define SYS_STACKING_SRC_PORT_MODE_GCHIP            2
#define SYS_STACKING_SRC_PORT_MODE_HASH             3

#define SYS_STK_TRUNK_BMP_NUM   ((MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) + CTC_UINT32_BITS) / CTC_UINT32_BITS)

#define SYS_STK_INIT_CHECK(lchip) \
    do { \
        LCHIP_CHECK(lchip); \
        if (NULL == g_stacking_master[lchip]){ \
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Feature not initialized \n");\
            return CTC_E_NOT_INIT;\
 } \
    } while (0)

#define SYS_STK_SEL_GRP_CHECK(grp_id, mode)           \
    if (SYS_STACKING_SRC_PORT_MODE_TRUNK_ID_GCHIP == g_stacking_master[lchip]->src_port_mode && ((grp_id) >= 8 || ((mode) && !(grp_id)))) \
    { return CTC_E_INVALID_PARAM; }

#define SYS_STK_DBG_OUT(level, FMT, ...) \
    do { \
        CTC_DEBUG_OUT(stacking, stacking, STK_SYS, level, FMT, ##__VA_ARGS__); \
    } while (0);
#define SYS_STK_MAX_LPORT_IN_WORD 16
#define SYS_STK_DBG_FUNC()          SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC,  "%s()\n", __FUNCTION__)
#define SYS_STK_DBG_DUMP(FMT, ...)  SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  FMT, ##__VA_ARGS__)
#define SYS_STK_DBG_INFO(FMT, ...)  SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO,  FMT, ##__VA_ARGS__)
#define SYS_STK_DBG_PARAM(FMT, ...) SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, FMT, ##__VA_ARGS__)

#define STACKING_LOCK \
    if (g_stacking_master[lchip]->p_stacking_mutex) sal_mutex_lock(g_stacking_master[lchip]->p_stacking_mutex)
#define STACKING_UNLOCK \
    if (g_stacking_master[lchip]->p_stacking_mutex) sal_mutex_unlock(g_stacking_master[lchip]->p_stacking_mutex)
/****************************************************************************
*
* Global and Declaration
*
*****************************************************************************/
enum sys_stacking_out_encap_e
{
    SYS_STK_OUT_ENCAP_NONE                = 0,  /* 4'b0000: BridgeHeader with no ipv4/ipv6   */
    SYS_STK_OUT_ENCAP_IPV4                = 1,  /* 4'b0001: BridgeHeader with ipv4           */
    SYS_STK_OUT_ENCAP_IPV6                = 2   /* 4'b0002: BridgeHeader with ipv6           */
};
typedef enum sys_stacking_out_encap_e sys_stacking_out_encap_t;

enum sys_stacking_opf_type_e
{
    SYS_STK_OPF_MEM_BASE,
    SYS_STK_OPF_BLOCK,
    SYS_STK_OPF_FWD,
    SYS_STK_OPF_ABILITY,
    SYS_STK_OPF_MCAST_PROFILE,
    SYS_STK_OPF_MAX
};
typedef enum sys_stacking_opf_type_e sys_stacking_opf_type_t;

struct sys_stacking_trunk_info_s
{
    uint32 trunk_id : 8;
    uint32 mode:3;
    uint32 replace_en:1;
    uint32 select_mode:1;
    uint32 rsv:19;
    uint16 flow_cnt;
    uint16 max_mem_cnt;
    uint16 flow_base;
    uint16 mem_base;
    uint16 dsmet_offset;
    uint16 next_dsmet_offset;
    uint32 flag;

    ctc_stacking_hdr_encap_t* p_encap_hdr;
};
typedef struct sys_stacking_trunk_info_s sys_stacking_trunk_info_t;

struct sys_stacking_block_profile_s
{
    uint8 lchip;
    uint8 rsv;
	uint16 profile_id;
    uint32 calc_key_len[0];
    uint32 bitmap[SYS_STK_MAX_GCHIP][SYS_STK_MAX_LPORT_IN_WORD];
};
typedef struct sys_stacking_block_profile_s sys_stacking_block_profile_t;

struct sys_stacking_fwd_profile_s
{
    uint8 lchip;
    uint8 rsv;
	uint16 profile_id;
    uint32 calc_key_len[0];
    uint32 trunk[SYS_STK_MAX_GCHIP];
};
typedef struct sys_stacking_fwd_profile_s sys_stacking_fwd_profile_t;

struct sys_stacking_mcast_db_s
{
    uint8   type;  /*0: stacking truck profile; 1: keeplive group*/
    uint8   rsv;
    uint16  id;

    uint32   head_met_offset;
    uint32   tail_met_offset;

    uint8 append_en;
    uint8 alloc_id;
    uint16 mcast_prf_id;
    uint32 last_tail_offset;

    uint32 trunk_bitmap[CTC_STK_TRUNK_BMP_NUM];
};
typedef struct sys_stacking_mcast_db_s sys_stacking_mcast_db_t;

struct sys_stacking_master_s
{
    uint8 fabric_mode;
	uint8 opf_type;
	uint8 trunk_mode;
	uint8 src_port_mode;  /*0: use src gport+remote chip to select ucast path, 1:use forward select group id+remote chip, 2: compatible mode*/

    uint32 stacking_mcast_offset;

    uint8 mcast_mode;/*0: add trunk to mcast group auto; 1: add trunk to mcast group by user*/
    uint8 binding_trunk;/*0: binding port to trunk auto when add port to trunk; 1: binding by user*/
    uint8 bind_mcast_en;
    uint8 stacking_ver;
    ctc_vector_t* p_trunk_vec;

	sys_stacking_block_profile_t* p_block_profile[SYS_STK_PORT_BLOCK_PROFILE_NUM];
	ctc_spool_t*   p_block_prof_spool;

    sys_stacking_fwd_profile_t* p_fwd_profile[SYS_STK_PORT_FWD_PROFILE_NUM];
    ctc_spool_t*   p_fwd_prof_spool;

    ctc_hash_t* mcast_hash;
    sys_stacking_mcast_db_t *p_default_prof_db;

    ctc_port_bitmap_t ing_port_en_bmp;               /*0:enable stk port when add trunk port, 1: enable stk port by API CTC_STK_PROP_STK_PORT_EN*/
    ctc_port_bitmap_t egr_port_en_bmp;               /*0:enable stk port when add trunk port, 1: enable stk port by API CTC_STK_PROP_STK_PORT_EN*/

    sal_mutex_t* p_stacking_mutex;

    uint16  max_gchip_id;
    uint16  max_block_port_id;
    uint8   isolation_mode;                    /*global isolation mode for CTC_STK_STOP_MODE_BLOCK_RCHIP_PORT*/
};
typedef struct sys_stacking_master_s sys_stacking_master_t;

#define SYS_STK_TRUNKID_RANGE_CHECK(val) \
    { \
        if ((val) < SYS_STK_TRUNK_MIN_ID || (val) > MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID)){ \
            return CTC_E_INVALID_PARAM; } \
        if ((g_stacking_master[lchip]->trunk_mode == CTC_STACKING_TRUNK_MODE_0) && (val >= MCHIP_CAP(SYS_CAP_STK_TRUNK_MEMBERS)/8))  \
        {                \
            return CTC_E_INVALID_PARAM;   \
        }                \
        if ((g_stacking_master[lchip]->trunk_mode == CTC_STACKING_TRUNK_MODE_1) && (val >= MCHIP_CAP(SYS_CAP_STK_TRUNK_MEMBERS)/32)) \
        {                \
            return CTC_E_INVALID_PARAM;   \
        }                \
    }

#define SYS_STK_CHIPID_CHECK(gchip) \
    { \
        if ((gchip) > g_stacking_master[lchip]->max_gchip_id || (gchip) == CTC_LINKAGG_CHIPID){ \
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid global chip id \n");\
			return CTC_E_INVALID_CHIP_ID;\
        } \
    }

#define SYS_STK_DSCP_CHECK(dscp) \
    { \
        if ((dscp) > 63){ \
            return CTC_E_INVALID_PARAM; } \
    }

#define SYS_STK_COS_CHECK(dscp) \
    { \
        if ((dscp) > 7){ \
            return CTC_E_INVALID_PARAM; } \
    }

#define SYS_STK_LPORT_CHECK(lport) \
    { \
        if ((lport) >= MCHIP_CAP(SYS_CAP_STK_MAX_LPORT)){ \
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk member port not valid\n");\
			return CTC_E_INVALID_PORT;\
        } \
    }

#define SYS_NH_NEXT_MET_ENTRY(lchip, dsmet_offset) ((SYS_NH_INVALID_OFFSET == dsmet_offset)?\
                                                         SYS_NH_INVALID_OFFSET : dsmet_offset)
#define SYS_STK_WRITE_SGMAC(lchip, index, value)\
    if(DRV_FROM_AT(lchip)){\
            cmd = DRV_IOW(DsMetFifoExcpSgmacMap_t, ((index)&0x7));\
            (DRV_FIELD_IOCTL(lchip, ((index)>>3), cmd, &value));}\

#define SYS_STK_PORT_NUM_MAX 512
#define SYS_USW_STK_ENCODE_BLOCK_INDEX(lchip, chip, profile_id, loop, out_index) \
    do{ \
    uint8 chip_shift;\
    uint8 profile_shift;\
    uint8 profile_num;\
    _sys_usw_stacking_get_isolation_info(lchip, &chip_shift, &profile_shift, &profile_num);\
    out_index = ((chip) << chip_shift | (profile_id) << profile_shift | loop); \
    }while(0)

sys_stacking_master_t* g_stacking_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

/****************************************************************************
*
* Function
*
**
***************************************************************************/
extern int32 sys_usw_l2_reserve_rchip_ad_index(uint8 lchip, uint8 gchip, uint16 max_port_num, uint8 rchip_slice_bmp);
extern int32 sys_usw_l2_free_rchip_ad_index(uint8 lchip, uint8 gchip, uint16 max_port_num);
extern int32 sys_usw_l2_get_rchip_rsv_ad(uint8 lchip, uint8 gchip, uint16* p_rsv_num);
extern int32 sys_usw_l2_wb_sync_rchip_rsv_ad(uint8 lchip, uint16** rchip_ad_rsv);
extern int32 sys_usw_l2_wb_restore_rchip_rsv_ad(uint8 lchip, uint16** rchip_ad_rsv);
STATIC int32 _sys_usw_stacking_get_isolation_info(uint8 lchip, uint8* p_chip_shift, uint8*p_profile_shift, uint8*p_profile_num);
extern int32 _sys_usw_stacking_get_member_ports(uint8 lchip, uint8 trunk_id, uint32* p_gports, uint8* cnt);
#define ____INTERNAL______
STATIC uint32
_sys_usw_stacking_dlb_flows2driver(uint8 lchip, uint16 num_flow)
{
    uint8 driver_value = 0;

    if (!DRV_FROM_TMM(lchip))
    {
        return 3;
    }

    switch (num_flow)
    {
        case 16:
            driver_value = 0;
            break;
        case 32:
            driver_value = 1;
            break;
        case 64:
            driver_value = 2;
            break;
        case 128:
            driver_value = 3;
            break;
        case 256:
            driver_value = 4;
            break;
        case 512:
            driver_value = 5;
            break;
        case 1024:
            driver_value = 6;
            break;
        case 2048:
            driver_value = 7;
            break;
        case 4096:
            driver_value = 8;
            break;
        case 8192:
            driver_value = 9;
            break;
        default:
            driver_value = 7;
    }

    return driver_value;
}

int32
_sys_usw_stacking_set_learning_mode(uint8 lchip, ctc_stacking_learning_mode_t learning_mode)
{
    uint32 cmd;
    uint32 value;
    IpeHeaderAdjustCtl_m headeradj;
    uint8 learn_cache_en = DRV_FROM_AT(lchip) && (drv_vchip_get_core_num(lchip) > 1) ? 1 : 0;

    SYS_STK_INIT_CHECK(lchip);

    value = (learning_mode == CTC_STK_LEARNING_MODE_NONE) ? 0:1;
    cmd = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_learningOnStacking_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    cmd = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_learningOnStacking_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    cmd = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_learningOnStacking_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    cmd = DRV_IOW(IpeHeaderAdjustCtl_t, IpeHeaderAdjustCtl_learningOnStacking_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    cmd = DRV_IOW(IpeLookupCtl_t, IpeLookupCtl_learningOnStacking_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOR(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &headeradj));
    SetIpeHeaderAdjustCtl(V, learningOnStacking_f, &headeradj, value);

    value =(learn_cache_en || (learning_mode == CTC_STK_LEARNING_MODE_NONE)) ? 0:1;
    cmd = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_stackingLearningType_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    if (CTC_STACKING_VERSION_1_0 == g_stacking_master[lchip]->stacking_ver)
    {
        SetIpeHeaderAdjustCtl(V, stackingMacLearningMode_f, &headeradj, 1);
    }
    else if (CTC_STACKING_VERSION_2_0 == g_stacking_master[lchip]->stacking_ver)
    {
        SetIpeHeaderAdjustCtl(V, stackingMacLearningMode_f, &headeradj, (learning_mode?0:1));
    }
    cmd = DRV_IOW(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &headeradj));

    if (CTC_STACKING_VERSION_2_0 == g_stacking_master[lchip]->stacking_ver)
    {
        value = (learning_mode == CTC_STK_LEARNING_MODE_BY_STK_HDR)?1:0;
        cmd = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_cfHeaderLearningEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }

    value = (g_stacking_master[lchip]->stacking_ver == CTC_STACKING_VERSION_1_0) ? 1 : (learning_mode ? 0:1);
    cmd = DRV_IOW(IpeLookupCtl_t, IpeLookupCtl_stackingMacLearningMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    cmd = DRV_IOW(IpeHeaderAdjustCtl_t, IpeHeaderAdjustCtl_stackingMacLearningMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    value = (learning_mode == CTC_STK_LEARNING_MODE_BY_PKT) ? 0:1;
    cmd = DRV_IOW(IpeFwdCtl_t, IpeFwdCtl_macLearningMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    return CTC_E_NONE;
}

/***********************************************************
** SPOOL functions
************************************************************/
#define ______SPOOL______
STATIC uint32
_sys_usw_stacking_block_profile_hash_make(sys_stacking_block_profile_t* backet)
{

    uint8* data                    = NULL;
    uint32   length                = 0;

    if (!backet)
    {
        return 0;
    }

    data = (uint8*)&backet->bitmap;
    length = sizeof(backet->bitmap);

    return ctc_hash_caculate(length, data);
}

STATIC bool
_sys_usw_stacking_block_profile_hash_compare(sys_stacking_block_profile_t* p_bucket,
                                               sys_stacking_block_profile_t* p_new)
{
    if (!p_bucket || !p_new)
    {
        return FALSE;
    }

    if (CTC_MAX_UINT16_VALUE == p_bucket->profile_id)/*for spool add error rollback*/
    {
        return TRUE;
    }

    if (!sal_memcmp(p_bucket->bitmap, p_new->bitmap, sizeof(p_bucket->bitmap)))
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_stacking_block_profile_index_alloc(sys_stacking_block_profile_t* p_block_profile,
                                              uint8* p_lchip)
{
    uint32 value_32 = 0;
    sys_usw_opf_t  opf;
    int32 ret = CTC_E_NONE;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = *p_lchip;
#endif
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[*p_lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_BLOCK;

    if ( CTC_WB_STATUS(*p_lchip) == CTC_WB_STATUS_RELOADING)
    {
        ret = sys_usw_opf_alloc_offset_from_position(*p_lchip, &opf, 1, p_block_profile->profile_id);
    }
    else
    {
        ret = sys_usw_opf_alloc_offset(*p_lchip, &opf, 1, &value_32);
        p_block_profile->profile_id = value_32&CTC_MAX_UINT16_VALUE;
    }

    SYS_STK_DBG_INFO("stacking_block_profile_index_alloc :%d\n",p_block_profile->profile_id);

    return ret;
}

STATIC int32
_sys_usw_stacking_block_profile_index_free(sys_stacking_block_profile_t* p_block_profile, uint8* p_lchip)
{
    uint32 value_32 = 0;
    sys_usw_opf_t  opf;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = *p_lchip;
#endif
    value_32 = p_block_profile->profile_id;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[*p_lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_BLOCK;
    CTC_ERROR_RETURN(sys_usw_opf_free_offset(*p_lchip, &opf, 1, value_32));

    SYS_STK_DBG_INFO("stacking_block_profile_index_free :%d\n",value_32);
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_stacking_add_block_port_profile(uint8 lchip,
                                           ctc_stacking_stop_rchip_t *p_stop_rchip,
                                           sys_stacking_block_profile_t** pp_profile_get)
{
    uint32 cmd                     = 0;
    uint32 lport                   = 0;
    uint8 rchip                    = 0;
    uint32 port_block_sel          = 0;
	sys_stacking_block_profile_t* p_profile_old = NULL;
    sys_stacking_block_profile_t* p_new_profile = NULL;
    int32 ret = CTC_E_NONE;

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_stop_rchip->src_gport, lchip, lport);
    SYS_STK_LPORT_CHECK(lport);

    cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexDstIsolateGroupSel_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_block_sel));

    p_new_profile = (sys_stacking_block_profile_t*)mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_block_profile_t));
    if (NULL == p_new_profile)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_new_profile, 0, sizeof(sys_stacking_block_profile_t));

    p_profile_old = g_stacking_master[lchip]->p_block_profile[port_block_sel];

    if (p_profile_old)
    {
        sal_memcpy(p_new_profile->bitmap, p_profile_old->bitmap, sizeof(p_new_profile->bitmap));
    }


    rchip = p_stop_rchip->rchip;
    sal_memcpy(p_new_profile->bitmap[rchip], p_stop_rchip->pbm, SYS_STK_MAX_LPORT_IN_WORD*sizeof(uint32));
    p_new_profile->lchip = lchip;
    CTC_ERROR_GOTO(ctc_spool_add(g_stacking_master[lchip]->p_block_prof_spool,
                                   p_new_profile,
                                   p_profile_old,
                                   pp_profile_get), ret, out);

    port_block_sel = (*pp_profile_get)->profile_id;
    g_stacking_master[lchip]->p_block_profile[port_block_sel] = (*pp_profile_get);

out:
    if (p_new_profile)
    {
        mem_free(p_new_profile);
    }

    return ret;

}

STATIC int32
_sys_usw_stacking_add_static_block_port_profile(uint8 lchip)
{
    sys_stacking_block_profile_t* p_new_profile = NULL;
    int32 ret = CTC_E_NONE;

    p_new_profile = (sys_stacking_block_profile_t*)mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_block_profile_t));
    if (NULL == p_new_profile)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_new_profile, 0, sizeof(sys_stacking_block_profile_t));
    p_new_profile->lchip = lchip;
    ret = ctc_spool_static_add(g_stacking_master[lchip]->p_block_prof_spool,
                                   p_new_profile);
    mem_free(p_new_profile);

    return ret;
}

STATIC uint32
_sys_usw_stacking_fwd_profile_hash_make(sys_stacking_fwd_profile_t* backet)
{
    uint8* data                    = NULL;
    uint32   length                = 0;

    if (!backet)
    {
        return 0;
    }

    data = (uint8*)&backet->trunk;
    length = sizeof(backet->trunk);

    return ctc_hash_caculate(length, data);
}


STATIC bool
_sys_usw_stacking_fwd_profile_hash_compare(sys_stacking_fwd_profile_t* p_bucket,
                                               sys_stacking_fwd_profile_t* p_new)
{
    if (!p_bucket || !p_new)
    {
        return FALSE;
    }

    if (CTC_MAX_UINT16_VALUE == p_bucket->profile_id)/*for spool add error rollback*/
    {
        return TRUE;
    }

    if (!sal_memcmp(p_bucket->trunk, p_new->trunk, sizeof(p_bucket->trunk)))
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_stacking_fwd_profile_index_alloc(sys_stacking_fwd_profile_t* p_fwd_profile, uint8* p_lchip)
{
    uint32 value_32 = 0;
    sys_usw_opf_t  opf;
    int32 ret = CTC_E_NONE;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = *p_lchip;
#endif
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[*p_lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_FWD;

    if ( CTC_WB_STATUS(*p_lchip) == CTC_WB_STATUS_RELOADING)
    {
        ret = sys_usw_opf_alloc_offset_from_position(*p_lchip, &opf, 1, p_fwd_profile->profile_id);
    }
    else
    {
        ret = sys_usw_opf_alloc_offset(*p_lchip, &opf, 1, &value_32);
        p_fwd_profile->profile_id = value_32&CTC_MAX_UINT16_VALUE;
    }

    SYS_STK_DBG_INFO("stacking_fwd_profile_index_alloc :%d\n",p_fwd_profile->profile_id);
    return ret;
}

STATIC int32
_sys_usw_stacking_fwd_profile_index_free(sys_stacking_fwd_profile_t* p_fwd_profile, uint8* p_lchip)
{
    uint32 value_32 = 0;
    sys_usw_opf_t  opf;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = *p_lchip;
#endif
    value_32 = p_fwd_profile->profile_id;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[*p_lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_FWD;
    CTC_ERROR_RETURN(sys_usw_opf_free_offset(*p_lchip, &opf, 1, value_32));

    SYS_STK_DBG_INFO("stacking_fwd_profile_index_free :%d\n",value_32);
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_add_fwd_port_profile(uint8 lchip,
                                           ctc_stacking_trunk_t *p_trunk,
                                           uint32* p_profile, bool is_del)
{
    uint32 cmd                     = 0;
    uint32 lport                   = 0;
    uint32 rchip                   = 0;
    uint32 port_fwd_sel            = 0;
	sys_stacking_fwd_profile_t* p_profile_get = NULL;
    sys_stacking_fwd_profile_t* p_profile_old = NULL;
    sys_stacking_fwd_profile_t new_profile;

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->src_gport, lchip, lport);

    cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexFwdSgGroupSel_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_fwd_sel));

    sal_memset(&new_profile, 0, sizeof(new_profile));

    p_profile_old = g_stacking_master[lchip]->p_fwd_profile[port_fwd_sel];

    if (p_profile_old)
    {
        sal_memcpy(new_profile.trunk, p_profile_old->trunk, sizeof(new_profile.trunk));
    }

	rchip = p_trunk->remote_gchip;
	new_profile.trunk[rchip]= is_del?0: p_trunk->trunk_id;
    new_profile.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_add(g_stacking_master[lchip]->p_fwd_prof_spool,
                                   &new_profile,
                                   p_profile_old,
                                   &p_profile_get));

    port_fwd_sel = p_profile_get->profile_id ;
    g_stacking_master[lchip]->p_fwd_profile[port_fwd_sel] = p_profile_get;
    *p_profile = p_profile_get->profile_id;

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_stacking_add_static_fwd_port_profile(uint8 lchip)
{
    sys_stacking_fwd_profile_t new_profile;

    sal_memset(&new_profile, 0, sizeof(new_profile));
    new_profile.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_static_add(g_stacking_master[lchip]->p_fwd_prof_spool,
                                   &new_profile));
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_stacking_add_trunk_port_rchip(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint32 cmd                     = 0;
    uint32 index                   = 0;
    uint32 field_val               = 0;
    uint32 port_fwd_sel            = 0;
    uint32 rchip                   = 0;
    uint16 lport                   = 0;

    CTC_ERROR_RETURN(_sys_usw_stacking_add_fwd_port_profile(lchip, p_trunk, &port_fwd_sel, FALSE));

    for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
    {
        if (g_stacking_master[lchip]->p_fwd_profile[port_fwd_sel])
        {
            field_val = g_stacking_master[lchip]->p_fwd_profile[port_fwd_sel]->trunk[rchip];
        }
        else
        {
            field_val = 0;
        }


        index = (port_fwd_sel << 7) + rchip;
        cmd = DRV_IOW(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));
        SYS_STK_WRITE_SGMAC(lchip, index, field_val);
    }
    SYS_STK_DBG_INFO("add trunk rchip src port 0x%x, sel:%d\n",p_trunk->src_gport, port_fwd_sel);

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->src_gport, lchip, lport);
    CTC_ERROR_RETURN(sys_usw_port_api_set_property(lchip, p_trunk->src_gport, CTC_PORT_PROP_STK_GRP_ID, port_fwd_sel));


    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_remove_trunk_port_rchip(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint32 cmd                     = 0;
    uint32 index                   = 0;
    uint32 field_val               = 0;
    uint32 port_fwd_sel            = 0;
    uint32 rchip                   = 0;
    uint16 lport;

    CTC_ERROR_RETURN(_sys_usw_stacking_add_fwd_port_profile(lchip, p_trunk, &port_fwd_sel, TRUE));

    for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
    {
        if (g_stacking_master[lchip]->p_fwd_profile[port_fwd_sel])
        {
            field_val = g_stacking_master[lchip]->p_fwd_profile[port_fwd_sel]->trunk[rchip];
        }
        else
        {
            field_val = 0;
        }

        index = (port_fwd_sel << 7) + rchip;
        cmd = DRV_IOW(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));
        SYS_STK_WRITE_SGMAC(lchip, index, field_val);
    }
    SYS_STK_DBG_INFO("remove trunk rchip src port 0x%x, sel:%d\n",p_trunk->src_gport, port_fwd_sel);

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->src_gport, lchip, lport);
    CTC_ERROR_RETURN(sys_usw_port_api_set_property(lchip, p_trunk->src_gport, CTC_PORT_PROP_STK_GRP_ID, port_fwd_sel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_remove_trunk_path(uint8 lchip, uint8 trunk_id)
{
    uint32 port_fwd_sel            = 0;
    uint16 rchip                   = 0;
    uint16 lport                   = 0;
    uint32 cmd                     = 0;
    uint32 field_val               = 0;
    uint32 port_type = 0;
    uint8 gchip = 0;
    uint8 bpe_en = 0;
    uint32 index = 0;
    uint32* p_bmp = NULL;
    uint32* p_tmp_bmp = NULL;
    int32 ret = CTC_E_NONE;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    ctc_stacking_trunk_t trunk;

    sal_memset(&trunk, 0, sizeof(trunk));
    trunk.trunk_id = trunk_id;
    sys_usw_get_gchip_id(lchip, &gchip);
    CTC_ERROR_RETURN(sys_usw_nh_get_bpe_en(lchip, &bpe_en));
    if (0 != g_stacking_master[lchip]->src_port_mode)
    {
        return CTC_E_NONE;
    }
    p_bmp = (uint32*)mem_malloc(MEM_STK_MODULE, SYS_STK_MAX_GCHIP*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/32*sizeof(uint32));
    if (NULL == p_bmp)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_bmp, 0, SYS_STK_MAX_GCHIP*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/32*sizeof(uint32));

    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_STK_MAX_LPORT); lport++)
    {
        dmps_port_info.gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, lport);
        CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE,
        (void *)&port_type), ret,done);

        if (SYS_DMPS_NETWORK_PORT != port_type && !bpe_en && (SYS_DMPS_CPUMAC_NETWORK_PORT != port_type))
        {
            continue;
        }

        cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexFwdSgGroupSel_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_fwd_sel), ret,done);

        for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
        {
            p_tmp_bmp = (uint32*)p_bmp+rchip*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/32;
            index = (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)?(port_fwd_sel << 7) + rchip:(1 << 9) + rchip;
            cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val), ret,done);
            if (trunk_id != field_val)
            {
                continue;
            }
            CTC_BMP_SET(p_tmp_bmp, lport);
        }
    }

    for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
    {
        p_tmp_bmp = (uint32*)p_bmp + rchip*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/32;
        for (lport = 0; lport < MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM); lport++)
        {
            if (!CTC_BMP_ISSET(p_tmp_bmp, lport))
            {
                continue;
            }

            trunk.src_gport =  SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, lport);
            trunk.remote_gchip = rchip; 
            _sys_usw_stacking_remove_trunk_port_rchip(lchip, &trunk);
        }
    }

done:
    mem_free(p_bmp);
    return ret;
}

/***********************************************************
** TRUNK functions
************************************************************/
#define _____TRUNK_____ ""
STATIC int32
_sys_usw_stacking_get_member_ref_cnt(uint8 lchip, uint16 channel, uint16 *port_ref_cnt,uint8 excp_trunk_id)
{
    uint32 cmd                     = 0;
    uint32 cmd_r_group             = 0;
    uint16 mem_cnt                 = 0;
    uint16 mem_base                = 0;
    uint16 mem_idx                 = 0;
    uint8 mode                     = 0;
    uint32 mem_channel_id          = 0xFFFF;
    uint8 trunk_id                 = 0;
    uint8 step = 0;
    DsLinkAggregateChannelGroup_m  ds_link_aggregate_sgmac_group;

    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(ds_link_aggregate_sgmac_group));

    cmd_r_group = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);

    step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

    for(trunk_id = SYS_STK_TRUNK_MIN_ID; trunk_id < MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID); trunk_id++)
    {
        if(excp_trunk_id != 0xFF && (excp_trunk_id ==trunk_id) )
        {
          continue;
        }
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd_r_group, &ds_link_aggregate_sgmac_group));
        mem_cnt     = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group);
        mem_base    = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group);
        mode        = GetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group);

        if (0 == mem_cnt)
        {
            continue;
        }

        for (mem_idx = 0; mem_idx < mem_cnt; mem_idx++)
        {
            if (mode == 0 || mode == 2)
            {
                cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mem_base + mem_idx, cmd, &mem_channel_id));
            }
            else if(mode == 1)
            {
                cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DsLinkAggregateChannelMemberSet_array_0_channelId_f + mem_idx*step);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, trunk_id, cmd, &mem_channel_id));
            }

            if (channel == SYS_USW_CHANNEL_ENCODE(mem_channel_id))
            {
                (*port_ref_cnt)++;
                break;
            }

        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_check_port_status(uint8 lchip, uint32 gport, sys_qos_shape_profile_t* p_shp_profile)
{
    uint32 depth                   = 0;
    uint16 index = 0;

    CTC_ERROR_RETURN(sys_usw_queue_get_port_depth(lchip, gport, &depth));
    while (depth)
    {
        sal_task_sleep(2);
        if ((index++) > 500)
        {
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "the queue depth:(%d) \n", depth);
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " HW operation timed out \n");
            return CTC_E_HW_TIME_OUT;
        }
        CTC_ERROR_RETURN(sys_usw_queue_get_port_depth(lchip, gport, &depth));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_get_trunk_info(uint8 lchip, uint8 trunk_id,
                                   uint16* cur_mem_cnt, uint16* mem_base, uint8* is_dlb)
{
    uint32 cmd = 0;
    uint8 noempty = 0;
    DsLinkAggregateChannelGroup_m  ds_link_aggregate_sgmac_group;

    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(ds_link_aggregate_sgmac_group));

    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group));

	*cur_mem_cnt = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group);
    noempty = GetDsLinkAggregateChannelGroup(V, grpNotEmpty_f, &ds_link_aggregate_sgmac_group);
    if(DRV_IS_TMG(lchip)&&noempty&&!(*cur_mem_cnt))
    {
        *cur_mem_cnt = MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS);
    }
	*mem_base    = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group);
    *is_dlb      = (GetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group) == 1)?1:0;

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_stacking_trunk_alloc_mem_base(uint8 lchip,
                                         sys_stacking_trunk_info_t* p_sys_trunk,
                                         uint16 max_mem_cnt, uint16* mem_base)
{
    uint32 value_32 = 0;
	uint8  trunk_id = 0;
    sys_usw_opf_t  opf;

    trunk_id = p_sys_trunk->trunk_id;
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_MEM_BASE;
    switch(g_stacking_master[lchip]->trunk_mode)
    {
    case CTC_STACKING_TRUNK_MODE_0:
        if (trunk_id >= MCHIP_CAP(SYS_CAP_STK_TRUNK_MEMBERS) / 8)
        {
           return CTC_E_INVALID_PARAM;
        }
        CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, 8, &value_32));
        *mem_base = value_32;
        p_sys_trunk->mem_base = *mem_base;
        p_sys_trunk->max_mem_cnt = 8;
        break;

    case CTC_STACKING_TRUNK_MODE_1:
        if (trunk_id >= MCHIP_CAP(SYS_CAP_STK_TRUNK_MEMBERS) / 32)
        {
            return CTC_E_INVALID_PARAM;
        }

        if (p_sys_trunk->mode == CTC_STK_LOAD_DYNAMIC)
        {
            if (DRV_FROM_TMM(lchip))
            {
                max_mem_cnt = 32;
                CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset(lchip, DsLagDlbFlowSetTable_t,
                                                                0, max_mem_cnt, 1, &value_32));
                *mem_base = value_32;
                p_sys_trunk->flow_cnt = max_mem_cnt;

            }
            else
            {
                CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, 32, &value_32));
                *mem_base = value_32;
                p_sys_trunk->mem_base = *mem_base;
                p_sys_trunk->max_mem_cnt = 32;
            }
            p_sys_trunk->flow_base= *mem_base;


        }
        else
        {
            CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS), &value_32));
            *mem_base = value_32;
            p_sys_trunk->mem_base = *mem_base;
            p_sys_trunk->max_mem_cnt = MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS);

        }

        break;

    case CTC_STACKING_TRUNK_MODE_2:
    case CTC_STACKING_TRUNK_MODE_3:
    case CTC_STACKING_TRUNK_MODE_4:
    case CTC_STACKING_TRUNK_MODE_5:
    case CTC_STACKING_TRUNK_MODE_6:
        if (DRV_FROM_TMM(lchip) && p_sys_trunk->mode == CTC_STK_LOAD_DYNAMIC)
        {
            CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset(lchip, DsLagDlbFlowSetTable_t,
                                                            0, max_mem_cnt, 1, &value_32));
            *mem_base = value_32;
            p_sys_trunk->flow_base= *mem_base;
            p_sys_trunk->flow_cnt = max_mem_cnt;

        }
        else if (max_mem_cnt)
        {
            CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, max_mem_cnt, &value_32));

            *mem_base = value_32;
            p_sys_trunk->mem_base = *mem_base;
            p_sys_trunk->max_mem_cnt = max_mem_cnt;
        }

        break;

    default:
        return CTC_E_INVALID_PARAM;

    }


    SYS_STK_DBG_INFO("_sys_usw_stacking_trunk_alloc_mem_base :%d\n",*mem_base);

    return CTC_E_NONE;

}


STATIC int32
_sys_usw_stacking_trunk_free_mem_base(uint8 lchip,
                                        sys_stacking_trunk_info_t* p_sys_trunk,
                                        uint16 max_mem_cnt, uint16 mem_base)
{
    sys_usw_opf_t  opf;
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_MEM_BASE;
    switch(g_stacking_master[lchip]->trunk_mode)
    {
    case CTC_STACKING_TRUNK_MODE_0:
    case CTC_STACKING_TRUNK_MODE_1:
        if (DRV_FROM_TMM(lchip) && p_sys_trunk->flow_cnt)
        {
            CTC_ERROR_RETURN(sys_usw_ftm_free_table_offset(lchip, DsLagDlbFlowSetTable_t,
                                                           0, p_sys_trunk->flow_cnt, p_sys_trunk->flow_base));
        }
        if(p_sys_trunk->max_mem_cnt)
        {
            CTC_ERROR_RETURN(sys_usw_opf_free_offset(lchip, &opf, p_sys_trunk->max_mem_cnt, p_sys_trunk->mem_base));
        }
        break;

    case CTC_STACKING_TRUNK_MODE_2:
    case CTC_STACKING_TRUNK_MODE_3:
    case CTC_STACKING_TRUNK_MODE_4:
    case CTC_STACKING_TRUNK_MODE_5:
    case CTC_STACKING_TRUNK_MODE_6:
        if (DRV_FROM_TMM(lchip) && p_sys_trunk->flow_cnt)
        {
            CTC_ERROR_RETURN(sys_usw_ftm_free_table_offset(lchip, DsLagDlbFlowSetTable_t,
                                                           0, p_sys_trunk->flow_cnt, p_sys_trunk->flow_base));
        }

        if(p_sys_trunk->max_mem_cnt)
        {
            CTC_ERROR_RETURN(sys_usw_opf_free_offset(lchip, &opf, p_sys_trunk->max_mem_cnt, p_sys_trunk->mem_base));
        }

        break;

    default:
        return CTC_E_INVALID_PARAM;

    }

    SYS_STK_DBG_INFO("_sys_usw_stacking_trunk_free_mem_base :%d\n",mem_base);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_clear_flow_active(uint8 lchip, uint8 trunk_id)
{
    uint32 cmd_r                   = 0;
    uint32 cmd_w                   = 0;
    uint16 flow_num                = 0;
    uint32 flow_base               = 0;
    uint16 index                   = 0;
    DsLinkAggregateChannelGroup_m ds_link_aggregate_channel_group;

    cmd_r = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd_r, &ds_link_aggregate_channel_group));

    flow_base = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_channel_group);

    if (DRV_FROM_TMM(lchip))
    {
        uint8 cnt = 0;
        DsLagDlbFlowSetTable_m flow_set;

        cnt = GetDsLinkAggregateChannelGroup(V, channelLinkAggFlowNum_f, &ds_link_aggregate_channel_group);
        flow_num = CTC_CONST16 * (2 << cnt);

        /* clear active */
        cmd_r = DRV_IOR(DsLagDlbFlowSetTable_t, DRV_ENTRY_FLAG);
        cmd_w = DRV_IOW(DsLagDlbFlowSetTable_t, DRV_ENTRY_FLAG);

        for (index = 0; index < flow_num; index++)
        {
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, flow_base + index, cmd_r, &flow_set));
            SetDsLagDlbFlowSetTable(V, active_f, &flow_set, 0);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, flow_base + index, cmd_w, &flow_set));
        }
    }
    else
    {
        DsLinkAggregateChannelMember_m ds_link_aggregate_channel_member;

        flow_num = CTC_CONST32;

        /* clear active */
        cmd_r = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
        cmd_w = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);

        for (index = 0; index < flow_num; index++)
        {
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, flow_base + index, cmd_r, &ds_link_aggregate_channel_member));
            SetDsLinkAggregateChannelMember(V, active_f, &ds_link_aggregate_channel_member, 0);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, flow_base + index, cmd_w, &ds_link_aggregate_channel_member));
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_failover_add_member(uint8 lchip, uint8 trunk_id, uint32 gport)
{
    uint32 cmd                     = 0;
    uint32 channel_id              = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsLinkAggregateChannel_m linkagg_channel;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x gport =  %d \n", trunk_id, gport);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));
    dmps_port_info.gport = gport;

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));

    cmd = DRV_IOR(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));
    SetDsLinkAggregateChannel(V, groupType_f, &linkagg_channel, 1);
    SetDsLinkAggregateChannel(V, groupEn_f, &linkagg_channel, 1);
    SetDsLinkAggregateChannel(V, u1_g2_linkAggregationChannelGroup_f, &linkagg_channel, trunk_id);
    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_failover_del_member(uint8 lchip, uint8 trunk_id, uint32 gport)
{
    uint32 cmd                     = 0;
    uint32 channel_id               = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsLinkAggregateChannel_m linkagg_channel;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x gport =  %d \n", trunk_id, gport);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));
    dmps_port_info.gport = gport;

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));

    cmd = DRV_IOR(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));
    SetDsLinkAggregateChannel(V, groupType_f, &linkagg_channel, 0);
    SetDsLinkAggregateChannel(V, groupEn_f, &linkagg_channel, 0);
    SetDsLinkAggregateChannel(V, u1_g2_linkAggregationChannelGroup_f, &linkagg_channel, 0);
    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_dlb_add_member_channel(uint8 lchip, uint8 trunk_id, uint16 channel_id)
{
    uint32 cmd = 0;
    DsLinkAggregateChannel_m linkagg_channel;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "trunk_id = 0x%x channel_id =  %d \n", trunk_id, channel_id);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));

    SetDsLinkAggregateChannel(V, groupEn_f, &linkagg_channel, 1);
    SetDsLinkAggregateChannel(V, groupType_f, &linkagg_channel, 1);
    SetDsLinkAggregateChannel(V, linkChangeEn_f, &linkagg_channel, 0);
    SetDsLinkAggregateChannel(V, u1_g2_linkAggregationChannelGroup_f, &linkagg_channel, trunk_id);

    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_dlb_del_member_channel(uint8 lchip, uint8 trunk_id, uint16 channel_id)
{
    uint32 cmd = 0;
    DsLinkAggregateChannel_m linkagg_channel;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "trunk_id = 0x%x channel_id =  %d \n", trunk_id, channel_id);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));

    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_dlb_add_member(uint8 lchip, uint8 trunk_id, uint8 port_index, uint16 channel_id)
{
    uint32 cmd = 0;
    DsLinkAggregateChannelMemberSet_m mem_set;
    uint8 step = 0;

    step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

    cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &mem_set));

    SetDsLinkAggregateChannelMemberSet(V, array_0_channelId_f + port_index*step, &mem_set, SYS_USW_CHANNEL_ENCODE(channel_id));
    SetDsLinkAggregateChannelMemberSet(V, array_0_sliceId_f + port_index*step, &mem_set, 0); /*TODO: multi-slice!!!!!!!!*/
    SetDsLinkAggregateChannelMemberSet(V, array_0_valid_f + port_index*step, &mem_set, 1);

    cmd = DRV_IOW(DsLinkAggregateChannelMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &mem_set));

    CTC_ERROR_RETURN(_sys_usw_stacking_dlb_add_member_channel(lchip, trunk_id, channel_id));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_dlb_del_member(uint8 lchip, uint8 trunk_id, uint8 port_index, uint8 tail_index, uint16 channel_id)
{
    uint32 cmd                     = 0;
    uint16 chan_tmp = 0;
    DsLinkAggregateChannelMemberSet_m mem_set;
    uint8 step = 0;

    step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

    cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &mem_set));

    /* copy the last one to the removed position */
    chan_tmp = GetDsLinkAggregateChannelMemberSet(V,  array_0_channelId_f + tail_index*step, &mem_set);
    SetDsLinkAggregateChannelMemberSet(V, array_0_channelId_f + port_index*step, &mem_set, chan_tmp);
    SetDsLinkAggregateChannelMemberSet(V, array_0_sliceId_f + port_index*step, &mem_set, 0); /*TODO: multi-slice!!!!!!!!*/
    SetDsLinkAggregateChannelMemberSet(V, array_0_valid_f + port_index*step, &mem_set, 1);

    /* set the last one to invalid */
    SetDsLinkAggregateChannelMemberSet(V, array_0_channelId_f + tail_index*step, &mem_set, MCHIP_CAP(SYS_CAP_CHANID_DROP));
    SetDsLinkAggregateChannelMemberSet(V, array_0_valid_f + tail_index*step, &mem_set, 0);

    cmd = DRV_IOW(DsLinkAggregateChannelMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &mem_set));


    CTC_ERROR_RETURN(_sys_usw_stacking_dlb_del_member_channel(lchip, trunk_id, channel_id));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_hdr_set(uint8 lchip, ctc_stacking_hdr_glb_t* p_hdr_glb)
{
    uint32 cmd  = 0;
    uint32 ipv6_sa[CTC_IPV6_ADDR_LEN] = {0};
    IpeHeaderAdjustCtl_m ipe_header_adjust_ctl;
    EpePktHdrCtl_m epe_pkt_hdr_ctl;

    SYS_STK_DSCP_CHECK(p_hdr_glb->ip_dscp);
    SYS_STK_COS_CHECK(p_hdr_glb->cos);

    if (!DRV_IS_DUET2(lchip))
    {
        if (p_hdr_glb->udp_en
        ||  p_hdr_glb->ether_type == 0x0800
        || p_hdr_glb->ether_type == 0x86DD)
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    sal_memset(&ipe_header_adjust_ctl, 0, sizeof(ipe_header_adjust_ctl));
    cmd = DRV_IOR(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_header_adjust_ctl));

    sal_memset(&epe_pkt_hdr_ctl, 0, sizeof(epe_pkt_hdr_ctl));
    cmd = DRV_IOR(EpePktHdrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt_hdr_ctl));

    SetIpeHeaderAdjustCtl(V, headerMacDaCheckEn_f, &ipe_header_adjust_ctl, p_hdr_glb->mac_da_chk_en);
    SetIpeHeaderAdjustCtl(V, headerTpid_f, &ipe_header_adjust_ctl, p_hdr_glb->vlan_tpid);
    SetIpeHeaderAdjustCtl(V, headerEtherTypeCheckDisable_f, &ipe_header_adjust_ctl, p_hdr_glb->ether_type_chk_en?0:1);
    SetIpeHeaderAdjustCtl(V, headerEtherType_f, &ipe_header_adjust_ctl, p_hdr_glb->ether_type);
    SetIpeHeaderAdjustCtl(V, headerIpProtocol_f, &ipe_header_adjust_ctl, p_hdr_glb->ip_protocol);
    SetIpeHeaderAdjustCtl(V, headerUdpEn_f, &ipe_header_adjust_ctl, p_hdr_glb->udp_en);
    SetIpeHeaderAdjustCtl(V, udpSrcPort_f, &ipe_header_adjust_ctl, p_hdr_glb->udp_dest_port);
    SetIpeHeaderAdjustCtl(V, udpDestPort_f, &ipe_header_adjust_ctl, p_hdr_glb->udp_src_port);

    SetEpePktHdrCtl(V, tpid_f, &epe_pkt_hdr_ctl, p_hdr_glb->vlan_tpid);
    SetEpePktHdrCtl(V, headerEtherType_f, &epe_pkt_hdr_ctl, p_hdr_glb->ether_type);
    SetEpePktHdrCtl(V, headerIpProtocol_f, &epe_pkt_hdr_ctl, p_hdr_glb->ip_protocol);
    SetEpePktHdrCtl(V, headerTtl_f, &epe_pkt_hdr_ctl, p_hdr_glb->ip_ttl);
    SetEpePktHdrCtl(V, headerDscp_f, &epe_pkt_hdr_ctl, p_hdr_glb->ip_dscp);
    SetEpePktHdrCtl(V, headerCos_f, &epe_pkt_hdr_ctl, p_hdr_glb->cos);


    if (p_hdr_glb->is_ipv4)
    {
            SetEpePktHdrCtl(V, headerIpSa_f, &epe_pkt_hdr_ctl, p_hdr_glb->ipsa.ipv4);
    }
    else
    {
        ipv6_sa[0] = p_hdr_glb->ipsa.ipv6[3];
        ipv6_sa[1] = p_hdr_glb->ipsa.ipv6[2];
        ipv6_sa[2] = p_hdr_glb->ipsa.ipv6[1];
        ipv6_sa[3] = p_hdr_glb->ipsa.ipv6[0];
        SetEpePktHdrCtl(A, headerIpSa_f, &epe_pkt_hdr_ctl, ipv6_sa);
    }

    SetEpePktHdrCtl(V, headerUdpEn_f, &epe_pkt_hdr_ctl, p_hdr_glb->udp_en);
    SetEpePktHdrCtl(V, useUdpPayloadLength_f, &epe_pkt_hdr_ctl, 1);
    SetEpePktHdrCtl(V, useIpPayloadLength_f, &epe_pkt_hdr_ctl, 1);
    SetEpePktHdrCtl(V, udpSrcPort_f, &epe_pkt_hdr_ctl, p_hdr_glb->udp_src_port);
    SetEpePktHdrCtl(V, udpDestPort_f, &epe_pkt_hdr_ctl, p_hdr_glb->udp_dest_port);

    /*Encap header param*/
    cmd = DRV_IOW(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_header_adjust_ctl));

    cmd = DRV_IOW(EpePktHdrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt_hdr_ctl));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_hdr_get(uint8 lchip, ctc_stacking_hdr_glb_t* p_hdr_glb)
{
    uint32 cmd  = 0;
    uint32 ipv6_sa[CTC_IPV6_ADDR_LEN] = {0};
    IpeHeaderAdjustCtl_m ipe_header_adjust_ctl;
    EpePktHdrCtl_m epe_pkt_hdr_ctl;

    sal_memset(&ipe_header_adjust_ctl, 0, sizeof(ipe_header_adjust_ctl));
    cmd = DRV_IOR(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_header_adjust_ctl));

    sal_memset(&epe_pkt_hdr_ctl, 0, sizeof(epe_pkt_hdr_ctl));
    cmd = DRV_IOR(EpePktHdrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt_hdr_ctl));

    GetIpeHeaderAdjustCtl(V, headerMacDaCheckEn_f, &ipe_header_adjust_ctl);
    GetIpeHeaderAdjustCtl(V, headerTpid_f, &ipe_header_adjust_ctl);
    GetIpeHeaderAdjustCtl(V, headerEtherTypeCheckDisable_f, &ipe_header_adjust_ctl);
    GetIpeHeaderAdjustCtl(V, headerEtherType_f, &ipe_header_adjust_ctl);
    GetIpeHeaderAdjustCtl(V, headerIpProtocol_f, &ipe_header_adjust_ctl);
    GetIpeHeaderAdjustCtl(V, headerUdpEn_f, &ipe_header_adjust_ctl);
    GetIpeHeaderAdjustCtl(V, udpSrcPort_f, &ipe_header_adjust_ctl);
    GetIpeHeaderAdjustCtl(V, udpDestPort_f, &ipe_header_adjust_ctl);

    p_hdr_glb->mac_da_chk_en     = GetIpeHeaderAdjustCtl(V, headerMacDaCheckEn_f, &ipe_header_adjust_ctl);
    p_hdr_glb->vlan_tpid         = GetIpeHeaderAdjustCtl(V, headerTpid_f, &ipe_header_adjust_ctl);
    p_hdr_glb->ether_type_chk_en = GetIpeHeaderAdjustCtl(V, headerEtherTypeCheckDisable_f, &ipe_header_adjust_ctl) ? 0 : 1;
    p_hdr_glb->ether_type        = GetIpeHeaderAdjustCtl(V, headerEtherType_f, &ipe_header_adjust_ctl);

    p_hdr_glb->ip_protocol   = GetIpeHeaderAdjustCtl(V, headerIpProtocol_f, &ipe_header_adjust_ctl);
    p_hdr_glb->udp_en        = GetIpeHeaderAdjustCtl(V, headerUdpEn_f, &ipe_header_adjust_ctl);
    p_hdr_glb->udp_dest_port = GetIpeHeaderAdjustCtl(V, udpSrcPort_f, &ipe_header_adjust_ctl);
    p_hdr_glb->udp_src_port  = GetIpeHeaderAdjustCtl(V, udpDestPort_f, &ipe_header_adjust_ctl);

    p_hdr_glb->ip_protocol   = GetEpePktHdrCtl(V, headerIpProtocol_f, &epe_pkt_hdr_ctl);
    p_hdr_glb->ip_ttl        = GetEpePktHdrCtl(V, headerTtl_f, &epe_pkt_hdr_ctl);
    p_hdr_glb->ip_dscp       = GetEpePktHdrCtl(V, headerDscp_f, &epe_pkt_hdr_ctl);
    p_hdr_glb->cos           = GetEpePktHdrCtl(V, headerCos_f, &epe_pkt_hdr_ctl);


    p_hdr_glb->is_ipv4 = (p_hdr_glb->ether_type == 0x0800);

    GetEpePktHdrCtl(A, headerIpSa_f, &epe_pkt_hdr_ctl, ipv6_sa);

    if (p_hdr_glb->is_ipv4)
    {
        p_hdr_glb->ipsa.ipv4        = ipv6_sa[0];
    }
    else
    {
        sal_memcpy(p_hdr_glb->ipsa.ipv6, ipv6_sa, sizeof(ipv6_addr_t));
        p_hdr_glb->ipsa.ipv6[3] = ipv6_sa[0];
        p_hdr_glb->ipsa.ipv6[2] = ipv6_sa[1];
        p_hdr_glb->ipsa.ipv6[1] = ipv6_sa[2];
        p_hdr_glb->ipsa.ipv6[0] = ipv6_sa[3];
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_set_version(uint8 lchip, uint16 chan_id, uint8 version)
{
    uint32 cmd                     = 0;
    uint32 field_val               = 0;
    IpeHeaderAdjustCtl_m  ipe_hdr_adjust_ctl;
    IpeFwdCtl_m           ipe_fwd_ctl;
    EpeHdrAdjustCtl_m     epe_hdr_adjust_ctl;
    EpeHeaderEditCtl_m    epe_header_edit_ctl;
    IpeLoopbackHeaderAdjustCtl_m ipe_loop_hdr_adj_ctl;
    EpeHdrAdjustChanCtl_m    epe_header_chan_ctl;
    IpeHeaderAdjustCFHeaderCtl_m ipe_hdr_adjust_cf_ctl;
    IpeFwdLegacyCFHeaderCtl_m ipe_fwd_legacy_cf_ctl;
    EpeHeaderEditCFHeaderCtl_m epe_header_edit_cf_ctl;

    cmd = DRV_IOR(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_hdr_adjust_ctl));
    cmd = DRV_IOR(IpeFwdCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_ctl));
    cmd = DRV_IOR(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_adjust_ctl));
    cmd = DRV_IOR(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_header_edit_ctl));
    cmd = DRV_IOR(IpeLoopbackHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_loop_hdr_adj_ctl));
    cmd = DRV_IOR(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_header_chan_ctl));
    cmd = DRV_IOR(IpeHeaderAdjustCFHeaderCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_hdr_adjust_cf_ctl));
    cmd = DRV_IOR(IpeFwdLegacyCFHeaderCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_legacy_cf_ctl));
    cmd = DRV_IOR(EpeHeaderEditCFHeaderCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_header_edit_cf_ctl));

    if (DRV_FROM_TMM(lchip))
    {
        uint32 legacy_en[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
        sal_memset(legacy_en, (CTC_STACKING_VERSION_1_0 == version)? 0xFF:0, sizeof(legacy_en));
        if (chan_id != SYS_DMPS_INVALID_CHAN_ID)
        {
            (DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip))?GetIpeHeaderAdjustCtl(A, legacyCFHeaderEn_f, &ipe_hdr_adjust_ctl, legacy_en ): \
                GetIpeHeaderAdjustCFHeaderCtl(A, legacyCFHeaderEn_f, &ipe_hdr_adjust_cf_ctl, legacy_en );

            if (CTC_STACKING_VERSION_1_0 == version)
            {
                CTC_BIT_SET(legacy_en[chan_id / 32], chan_id % 32);
            }
            else
            {
                CTC_BIT_UNSET(legacy_en[chan_id / 32], chan_id % 32);
            }
        }

        SetIpeHeaderAdjustCtl(A, legacyCFHeaderEn_f, &ipe_hdr_adjust_ctl, legacy_en );
        SetIpeFwdCtl(A, legacyCFHeaderEn_f, &ipe_fwd_ctl, legacy_en );
        SetEpeHeaderEditCtl(A, legacyCFHeaderEn_f, &epe_header_edit_ctl, legacy_en);
        SetEpeHdrAdjustCtl(A, srcLegacyCFHeaderEn_f, &epe_hdr_adjust_ctl, legacy_en);
        SetEpeHdrAdjustChanCtl(A, dstLegacyCFHeaderEn_f, &epe_header_chan_ctl, legacy_en);
        SetIpeHeaderAdjustCFHeaderCtl(A, legacyCFHeaderEn_f, &ipe_hdr_adjust_cf_ctl, legacy_en );
        SetEpeHeaderEditCFHeaderCtl(A, legacyCFHeaderEn_f, &epe_header_edit_cf_ctl, legacy_en);
        SetIpeFwdLegacyCFHeaderCtl(A, legacyCFHeaderEn_f, &ipe_fwd_legacy_cf_ctl, legacy_en );
    }
    else
    {
        field_val = (CTC_STACKING_VERSION_1_0 == version)?1:0;

        SetIpeHeaderAdjustCtl(V, legacyCFHeaderEn_f, &ipe_hdr_adjust_ctl, field_val);
        SetIpeLoopbackHeaderAdjustCtl(V, legacyCFHeaderEn_f, &ipe_loop_hdr_adj_ctl, field_val);
        SetIpeFwdCtl(V, legacyCFHeaderEn_f, &ipe_fwd_ctl, field_val);
        SetEpeHdrAdjustCtl(V, legacyCFHeaderEn_f, &epe_hdr_adjust_ctl, field_val);
        SetEpeHeaderEditCtl(V, legacyCFHeaderEn_f, &epe_header_edit_ctl, field_val);
    }

    cmd = DRV_IOW(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_hdr_adjust_ctl));
    cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_ctl));
    cmd = DRV_IOW(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_adjust_ctl));
    cmd = DRV_IOW(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_header_edit_ctl));
    cmd = DRV_IOW(IpeLoopbackHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_loop_hdr_adj_ctl));
    cmd = DRV_IOW(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_header_chan_ctl));
    cmd = DRV_IOW(IpeHeaderAdjustCFHeaderCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_hdr_adjust_cf_ctl));
    cmd = DRV_IOW(IpeFwdLegacyCFHeaderCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_legacy_cf_ctl));
    cmd = DRV_IOW(EpeHeaderEditCFHeaderCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_header_edit_cf_ctl));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_get_version(uint8 lchip, uint16 chan_id, uint8* version)
{
    *version  = g_stacking_master[lchip]->stacking_ver;

    return CTC_E_NONE;
}

STATIC uint8
_sys_usw_stacking_get_port_mode(uint8 lchip)
{
   uint8 src_port_mode = 0;

   if (DRV_FROM_TMM(lchip))
   {
       if(CTC_STACKING_VERSION_2_0 == g_stacking_master[lchip]->stacking_ver)
       {
           src_port_mode = 0;
       }
       else
       {
           src_port_mode = 0x7;
       }
   }
   else
   {
       if (CTC_STACKING_VERSION_1_0 == g_stacking_master[lchip]->stacking_ver)
       {
           src_port_mode =  1;
       }
       else
       {
           src_port_mode =  0;
       }
   }

    return src_port_mode;
}

STATIC int32
_sys_usw_stacking_register_en(uint8 lchip, ctc_stacking_glb_cfg_t* p_glb_cfg)
{
    uint32 cmd                     = 0;
    uint32 value                   = 0;
    uint32 ds_nh_offset            = 0;
    uint32 value_mode              = 0;
    uint32 field_val               = 0;
    uint8 gchip_id                 = 0;
    uint16 sub_queue_id            = 0;
    uint8 grp_id                   = 0;
    uint32 packet_header_en[CTC_CONST16] = {0};
    uint32 chip_discard[SYS_STK_MAX_GCHIP/CTC_UINT32_BITS] = {0};
    uint8  table_buffer[CTC_CONST512];
    uint8  index = 0;

    value = 1;
    value_mode = (p_glb_cfg->fabric_mode == 1) ? 0 : value;
    sys_usw_get_gchip_id(lchip, &gchip_id);

    _sys_usw_stacking_set_version(lchip, SYS_DMPS_INVALID_CHAN_ID, p_glb_cfg->version);
    sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_STK_EN, 1, 0);
    /*IPE Hdr Adjust Ctl*/
    cmd = DRV_IOR(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetIpeHeaderAdjustCtl(V, packetHeaderBypassAll_f, &table_buffer, value);
    SetIpeHeaderAdjustCtl(V, discardNonPacketHeader_f, &table_buffer, value_mode);
    SetIpeHeaderAdjustCtl(V, cFlexLookupDestMap_f, &table_buffer, SYS_RSV_PORT_SPINE_LEAF_PORT);
    SetIpeHeaderAdjustCtl(V, cFlexLookupDestMapMask_f, &table_buffer, 0x2100FF);
    SetIpeHeaderAdjustCtl(V, useCflexHdrParserPara_f, &table_buffer, 1);
    sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_CFLEX_DEST_MAP, SYS_RSV_PORT_SPINE_LEAF_PORT, 0);
    sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_CFLEX_DEST_MAP_MASK, 0x2100FF, 0);

    /*SDK not support BrgHdr in CFlexHeader*/
    SetIpeHeaderAdjustCtl(V, cfHeaderLen_f, &table_buffer, 0);
    SetIpeHeaderAdjustCtl(V, packetHeaderAsCFlexHeader_f, &table_buffer, 0);
    SetIpeHeaderAdjustCtl(V, cFlexSkipHeaderParser_f, &table_buffer, 1);
    SetIpeHeaderAdjustCtl(V, forceSkipHeaderParser_f, &table_buffer, 1);
    SetIpeHeaderAdjustCtl(V, cflexDebugEn_f, &table_buffer, 1);


    if (CTC_STACKING_VERSION_1_0 == p_glb_cfg->version)
    {
        SetIpeHeaderAdjustCtl(V, toCpuQueSelType_f, &table_buffer, 1);
        SetIpeHeaderAdjustCtl(V, cFlexPacketTypeMode_f, &table_buffer, (p_glb_cfg->fabric_mode?1:0));
        SetIpeHeaderAdjustCtl(V, stackingMacLearningMode_f, &table_buffer, 1);
        SetIpeHeaderAdjustCtl(V, isCflexHeaderVersion_f, &table_buffer, 0x7);
        field_val = 0;
    }
    else if (CTC_STACKING_VERSION_2_0 == p_glb_cfg->version)
    {
        SetIpeHeaderAdjustCtl(V, cFlexPacketTypeMode_f, &table_buffer, 1);
        SetIpeHeaderAdjustCtl(V, stackingMacLearningMode_f, &table_buffer, (p_glb_cfg->learning_mode?0:1));
        if (((DRV_IS_TSINGMA(lchip) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A)) || DRV_FROM_TMM(lchip))
                && p_glb_cfg->fabric_mode == 1)
        {
            SetIpeHeaderAdjustCtl(V, cflexUseHeaderVlanPtr_f, &table_buffer, 1);
        }
        SetIpeHeaderAdjustCtl(V, cflexUseHeaderLogicSrcPort_f, &table_buffer, p_glb_cfg->fabric_mode?1:0);
        field_val = 1;
    }

    SetIpeHeaderAdjustCtl(V, sourcePortMode_f, &table_buffer,
                          _sys_usw_stacking_get_port_mode(lchip));

    cmd = DRV_IOW(IpeHeaderAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    cmd = DRV_IOW(OamHeaderAdjustCtl_t, OamHeaderAdjustCtl_useCFHeader_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    field_val = 1;
    cmd = DRV_IOW(IpeIntfMapperCtl_t, IpeIntfMapperCtl_bypassAllcFlexFwdSgGroupSelEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    cmd = DRV_IOW(IpeIntfMapperCtl_t, IpeIntfMapperCtl_bypassAllcFlexDstIsolateGroupSelEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    cmd = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_stackingLearningLogicPortEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    /*ingress edit*/
    cmd = DRV_IOR(IpeFwdCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    SetIpeFwdCtl(V, packetHeaderAsCFlexHeader_f, &table_buffer, 0);
    SetIpeFwdCtl(V, cfHeaderLen_f, &table_buffer, 0);
    SetIpeFwdCtl(V, logicSrcPort32kMode_f, &table_buffer, 0);
    SetIpeFwdCtl(V, cFlexIsolateType_f, &table_buffer, 0);
    SetIpeFwdCtl(V, globalPortIsolateType_f, &table_buffer, 0);
    SetIpeFwdCtl(V, ingressEditNexthopExt_f, &table_buffer, 0);
    SetIpeFwdCtl(V, ingressEditNexthopExtSpan_f, &table_buffer, 0);
    SetIpeFwdCtl(V, cfHeaderNextHopExt_f, &table_buffer, 0);
    SetIpeFwdCtl(V, ptpCflexEnable_f, &table_buffer, 1);
    SetIpeFwdCtl(V, cflexVlanEditMode_f, &table_buffer, 1);

    SetIpeFwdCtl(V, cFlexSrcIsolateFwdTypeEn_f, &table_buffer, 0xFFFFFFFF);
    SetIpeFwdCtl(V, c2cCheckDisable_f, &table_buffer, 0);
    SetIpeFwdCtl(V, cFlexDstIsolateMcastEn_f, &table_buffer, 1);
    SetIpeFwdCtl(V, cFlexDstIsolateUcastEn_f, &table_buffer, 0);
    SetIpeFwdCtl(V, cFlexSrcIsolateMode_f, &table_buffer, 1);
    SetIpeFwdCtl(V, fromCflexExceptionSupport_f, &table_buffer, 1);

    SetIpeFwdCtl(V, sourcePortMode_f, &table_buffer,
                 _sys_usw_stacking_get_port_mode(lchip));

    CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip,
    DRV_FROM_AT(lchip)?SYS_NH_RES_OFFSET_TYPE_STK_IGS_EDIT_BRG:SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH,  &ds_nh_offset));
    SetIpeFwdCtl(V, ingressEditNexthopPtr_f, &table_buffer, ds_nh_offset);

    CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip,
    SYS_NH_RES_OFFSET_TYPE_MIRROR_NH,  &ds_nh_offset));
    SetIpeFwdCtl(V, ingressEditNexthopPtrSpan_f, &table_buffer, ds_nh_offset);

    CTC_ERROR_RETURN(sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_C2C_PKT, &sub_queue_id));
    grp_id = (sub_queue_id / MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM)) + 1;
    /*to cpu based on prio*/
    field_val =  SYS_ENCODE_EXCP_DESTMAP_GRP(gchip_id, grp_id);

    SetIpeFwdCtl(V, neighborDiscoveryDestMap_f, &table_buffer, field_val);
    SetIpeFwdCtl(V, macLearningMode_f, &table_buffer, ((p_glb_cfg->learning_mode ==CTC_STK_LEARNING_MODE_BY_PKT) ?0:1));
    cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    /*Ipe Lookup Ctl*/
    cmd = DRV_IOR(IpeLookupCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    if (CTC_STACKING_VERSION_1_0 == p_glb_cfg->version)
    {
        SetIpeLookupCtl(V, stackingMacLearningMode_f, &table_buffer, 1);
    }
    else if (CTC_STACKING_VERSION_2_0 == p_glb_cfg->version)
    {
        SetIpeLookupCtl(V, stackingMacLearningMode_f, &table_buffer, (p_glb_cfg->learning_mode?0:1));
    }
    cmd = DRV_IOW(IpeLookupCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));


    /*Buffer Store Ctl init*/
    cmd = DRV_IOR(BufferStoreCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    if (!DRV_IS_DUET2(lchip))
    {
        CTC_BIT_SET(chip_discard[gchip_id / 32], gchip_id % 32);
        SetBufferStoreCtl(A, discardSourceChip_f, &table_buffer, chip_discard);
    }
    cmd = DRV_IOW(BufferStoreCtl_t, DRV_ENTRY_FLAG);
    SYS_SET_TBL_ALL_DP(lchip, cmd, table_buffer);

    /*MetFifo Ctl init*/
    cmd = DRV_IOR(MetFifoCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetMetFifoCtl(V, stackingMcastEndEn_f, &table_buffer, value);
    SetMetFifoCtl(V, exceptionResetSrcSgmac_f, &table_buffer, value);
    SetMetFifoCtl(V, uplinkReflectCheckEn_f, &table_buffer, value);
    SetMetFifoCtl(V, forceReplicationFromFabric_f, &table_buffer, value);
    SetMetFifoCtl(V, stackingBroken_f, &table_buffer, 0);
    SetMetFifoCtl(V, discardMetLoop_f, &table_buffer, 0);
    SetMetFifoCtl(V, fromRemoteCpuPhyPortCheckEn_f, &table_buffer, 1);
    SetMetFifoCtl(V, fromFabricPktToCflexLagHashSel_f, &table_buffer, 1);
    SetMetFifoCtl(V, destChipSgMacSelMode_f, &table_buffer, (p_glb_cfg->src_port_mode == SYS_STACKING_SRC_PORT_MODE_GCHIP)? 1 : 0);/*AT*/
    /*use hash to select trunk*/
    if (SYS_STACKING_SRC_PORT_MODE_HASH == p_glb_cfg->src_port_mode)
    {
        SetMetFifoCtl(V, fabricMode_f, &table_buffer, 1);
    }
    cmd = DRV_IOW(MetFifoCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    /*Qwrite Sgmac Ctl init*/
    cmd = DRV_IOR(QWriteSgmacCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetQWriteSgmacCtl(V, sgmacEn_f, &table_buffer, value);
    SetQWriteSgmacCtl(V, uplinkReflectCheckEn_f, &table_buffer, value_mode);
    SetQWriteSgmacCtl(V, discardUnkownSgmacGroup_f, &table_buffer, value);
    SetQWriteSgmacCtl(V, cFlexLagHashType_f, &table_buffer, 1);
    cmd = DRV_IOW(QWriteSgmacCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    /*Qwrite Port Isolation Ctl init*/
    if (DRV_FROM_AT(lchip))
    {
        /* McQWritePortIsolationCtl_t UcQWritePortIsolationCtl_t*/
        cmd = DRV_IOR(UcQWritePortIsolationCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

        SetUcQWritePortIsolationCtl(V, dstPhyPortMode_f, &table_buffer, 0);
        SetUcQWritePortIsolationCtl(V, cFlexDstIsolateC2cPacketEn_f, &table_buffer, 1);
        SetUcQWritePortIsolationCtl(V, cFlexDstIsolateFwdTypeEn1_f, &table_buffer, 0xF);
        SetUcQWritePortIsolationCtl(V, cFlexDstIsolateFwdTypeEn2_f, &table_buffer, 0xF);
        SetUcQWritePortIsolationCtl(V, cFlexDstIsolateUcastEn_f, &table_buffer, 0);
        SetUcQWritePortIsolationCtl(V, cFlexDstIsolateMode_f, &table_buffer, g_stacking_master[lchip]->isolation_mode);
        SetUcQWritePortIsolationCtl(V, overflowDiscard_f, &table_buffer, 0);
        cmd = DRV_IOW(UcQWritePortIsolationCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

        cmd = DRV_IOR(McQWritePortIsolationCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

        SetMcQWritePortIsolationCtl(V, dstPhyPortMode_f, &table_buffer, 0);
        SetMcQWritePortIsolationCtl(V, cFlexDstIsolateC2cPacketEn_f, &table_buffer, 1);
        SetMcQWritePortIsolationCtl(V, cFlexDstIsolateFwdTypeEn1_f, &table_buffer, 0xF);
        SetMcQWritePortIsolationCtl(V, cFlexDstIsolateFwdTypeEn2_f, &table_buffer, 0xF);
        SetMcQWritePortIsolationCtl(V, cFlexDstIsolateMcastEn_f, &table_buffer, 1);
        SetMcQWritePortIsolationCtl(V, cFlexDstIsolateMode_f, &table_buffer, g_stacking_master[lchip]->isolation_mode);
        SetMcQWritePortIsolationCtl(V, overflowDiscard_f, &table_buffer, 0);
        cmd = DRV_IOW(McQWritePortIsolationCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    }
    else
    {
        /* QWritePortIsolateCtl_t*/
        cmd = DRV_IOR(QWritePortIsolateCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

        SetQWritePortIsolateCtl(V, dstPhyPortMode_f, &table_buffer, 0);
        SetQWritePortIsolateCtl(V, cFlexDstIsolateC2cPacketEn_f, &table_buffer, 1);
        SetQWritePortIsolateCtl(V, cFlexDstIsolateFwdTypeEn1_f, &table_buffer, 0xF);
        SetQWritePortIsolateCtl(V, cFlexDstIsolateFwdTypeEn2_f, &table_buffer, 0xF);
        SetQWritePortIsolateCtl(V, cFlexDstIsolateMcastEn_f, &table_buffer, 1);
        SetQWritePortIsolateCtl(V, cFlexDstIsolateUcastEn_f, &table_buffer, 0);
        SetQWritePortIsolateCtl(V, cFlexDstIsolateMode_f, &table_buffer, g_stacking_master[lchip]->isolation_mode);
        SetQWritePortIsolateCtl(V, overFlowDiscard_f, &table_buffer, 0);
        cmd = DRV_IOW(QWritePortIsolateCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    }

    /*Epe Head Adjust Ctl init*/
    cmd = DRV_IOR(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    SetEpeHdrAdjustCtl(V, egressCpuRemoveByteType_f, &table_buffer, 0);
    SetEpeHdrAdjustCtl(V, egressCpuNotStripPacket_f, &table_buffer, 1);
    SetEpeHdrAdjustCtl(V, toRemoteCpuSkipPacketEdit_f, &table_buffer, 1);
    SetEpeHdrAdjustCtl(V, toRemoteCpuAttachHeader_f, &table_buffer, 0);
    SetEpeHdrAdjustCtl(V, cfHeaderLen_f, &table_buffer, 0);
    SetEpeHdrAdjustCtl(V, packetHeaderAsCFlexHeader_f, &table_buffer, 0);
    SetEpeHdrAdjustCtl(V, cFlexPtpApplyEgressAsymmetryDelay_f, &table_buffer, 1);
    SetEpeHdrAdjustCtl(V, packetHeaderBypassAll_f, &table_buffer, 1);
    SetEpeHdrAdjustCtl(V, cflexGlbDestPortEn_f, &table_buffer, 1);

    if (CTC_STACKING_VERSION_1_0 == p_glb_cfg->version)
    {
        SetEpeHdrAdjustCtl(V, cFlexPtpEnable_f, &table_buffer, 0);
    }
    else
    {
        SetEpeHdrAdjustCtl(V, cFlexPtpEnable_f, &table_buffer, 1);
    }

    cmd = DRV_IOW(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    cmd = DRV_IOR(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    GetEpeHdrAdjustChanCtl(A, packetHeaderEditIngress_f, &table_buffer, packet_header_en);
    {
        sal_memset(packet_header_en, 0xFF, sizeof(packet_header_en));
    }
    SetEpeHdrAdjustChanCtl(A, packetHeaderEditIngress_f, &table_buffer, packet_header_en);

    cmd = DRV_IOW(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));


    /*Epe Nexthop Ctl init*/
    cmd = DRV_IOR(EpeNextHopCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetEpeNextHopCtl(V, cFlexDot1QEn1_f, &table_buffer, 1);
    if (CTC_STACKING_VERSION_1_0 == p_glb_cfg->version)
    {
        SetEpeNextHopCtl(V, stackingDot1QEn_f, &table_buffer, 1);
    }
    else if (CTC_STACKING_VERSION_2_0 == p_glb_cfg->version)
    {
        SetEpeNextHopCtl(V, stackingDot1QEn_f, &table_buffer, 0);
    }
    cmd = DRV_IOW(EpeNextHopCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    /*Epe Packet Process Ctl init*/
    cmd = DRV_IOR(EpePktProcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetEpePktProcCtl(V, cfPathSkipTimestamp_f, &table_buffer, 0);
    SetEpePktProcCtl(V, ingEditSkipVlanEdit_f, &table_buffer, 0);
    cmd = DRV_IOW(EpePktProcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    /*Epe Header Edit Ctl init*/
    cmd = DRV_IOR(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetEpeHeaderEditCtl(V, stackingEn_f, &table_buffer, value);
    SetEpeHeaderEditCtl(V, stackingCompatibleMode_f, &table_buffer, value);

    SetEpeHeaderEditCtl(V, headerVersion_f, &table_buffer, 2);
    SetEpeHeaderEditCtl(V, useEgressNewTpid_f, &table_buffer, 0);
    SetEpeHeaderEditCtl(V, ecnCriticalPacketEn_f, &table_buffer, 0);
    SetEpeHeaderEditCtl(V, ingressEditUseLogicPortSelect_f, &table_buffer, 0);
    SetEpeHeaderEditCtl(V, extEgrEditValid_f, &table_buffer, 0);
    SetEpeHeaderEditCtl(V, extCidValid_f, &table_buffer, 0);
    SetEpeHeaderEditCtl(V, extLearningValid_f, &table_buffer, 0);
    SetEpeHeaderEditCtl(V, extHeaderDisableBitmap_f, &table_buffer, 0);
    SetEpeHeaderEditCtl(V, cflexDebugEn_f, &table_buffer, 1);
    SetEpeHeaderEditCtl(V, spanPktUseSrcPortOnCFlex_f, &table_buffer, 1);
    SetEpeHeaderEditCtl(V, fabricStatsSkipCflexHdr_f, &table_buffer, 1); /*epe stats remove stacking header*/
    if (CTC_STACKING_VERSION_2_0 == p_glb_cfg->version)
    {
        SetEpeHeaderEditCtl(V, cfHeaderLearningEn_f, &table_buffer, (p_glb_cfg->learning_mode ==CTC_STK_LEARNING_MODE_BY_STK_HDR)?1:0);
    }

    SetEpeHeaderEditCtl(V, sourcePortMode_f, &table_buffer,
                        _sys_usw_stacking_get_port_mode(lchip));


    cmd = DRV_IOW(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    /*Epe Packet Header Ctl init*/
    cmd = DRV_IOR(EpePktHdrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetEpePktHdrCtl(V, headerUdpEn_f, &table_buffer, 0);
    SetEpePktHdrCtl(V, cFlexLookupDestMap_f, &table_buffer, SYS_RSV_PORT_SPINE_LEAF_PORT);
    SetEpePktHdrCtl(V, cFlexLookupDestMapMask_f, &table_buffer, 0x400FF);
    SetEpePktHdrCtl(V, cFlexPortEcnEn_f, &table_buffer, 1);
    SetEpePktHdrCtl(V, skipHeaderEditingEn_f, &table_buffer, 0);
    SetEpePktHdrCtl(V, skipHeaderDestMap_f, &table_buffer, SYS_RSV_PORT_SPINE_LEAF_PORT);
    SetEpePktHdrCtl(V, skipHeaderDestMapMask_f, &table_buffer, 0x400FF);
    SetEpePktHdrCtl(V, packetHeaderAsCFlexHeader_f, &table_buffer, 0);
    SetEpePktHdrCtl(V, cFlexDisableMarkCnAcion_f, &table_buffer, 0);
    cmd = DRV_IOW(EpePktHdrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

    /*Lag Engine Ctl init*/
    cmd = DRV_IOR(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    SetLagEngineCtl(V, sgmacEn_f, &table_buffer, value);
    SetLagEngineCtl(V, sgmacGroupId0Valid_f, &table_buffer, value);
    SetLagEngineCtl(V, channelGroupEmptyChkEn_f, &table_buffer, value);
    SetLagEngineCtl(V, discardUnkownSgmacGroup_f, &table_buffer, value);
    SetLagEngineCtl(V, chanLagMemberMoveCheckEn_f, &table_buffer, 1);
    SetLagEngineCtl(V, sgHashMode_f, &table_buffer, 1);
    SetLagEngineCtl(V, cflexLagLshEn_f, &table_buffer, 0x7); /*TMM (rrEn,staticLbEn,resilientHashEn)*/
    SetLagEngineCtl(V, cflexLagLshHashSelectCfg_f, &table_buffer, 2); /*default*/
    SetLagEngineCtl(V, cflexLagLshHashOffsetCfg_f, &table_buffer, 0);
    SetLagEngineCtl(V, destChipSgMacSelMode_f, &table_buffer, (p_glb_cfg->src_port_mode == SYS_STACKING_SRC_PORT_MODE_GCHIP)?1:0);
    /*use hash to select trunk*/
    if (SYS_STACKING_SRC_PORT_MODE_HASH == p_glb_cfg->src_port_mode)
    {
        SetLagEngineCtl(V, fabricMode_f, &table_buffer, 1);
        SetLagEngineCtl(V, sgHashMode_f, &table_buffer, 0);
    }
    cmd = DRV_IOW(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));


    /*to cpu*/
    if (CTC_STACKING_VERSION_1_0 == p_glb_cfg->version)
    {
        sal_memset(&table_buffer, 0, sizeof(IpeLegacyCFHeaderXlateCtl_m));
        SetIpeLegacyCFHeaderXlateCtl(V, g_0_toCpu_f, &table_buffer, 0);
        SetIpeLegacyCFHeaderXlateCtl(V, g_1_toCpu_f, &table_buffer, 1);
        SetIpeLegacyCFHeaderXlateCtl(V, g_2_toCpu_f, &table_buffer, 0);
        SetIpeLegacyCFHeaderXlateCtl(V, g_3_toCpu_f, &table_buffer, 0);
        SetIpeLegacyCFHeaderXlateCtl(V, g_4_toCpu_f, &table_buffer, 0);
        SetIpeLegacyCFHeaderXlateCtl(V, g_5_toCpu_f, &table_buffer, 0);
        SetIpeLegacyCFHeaderXlateCtl(V, g_6_toCpu_f, &table_buffer, 1);
        SetIpeLegacyCFHeaderXlateCtl(V, g_7_toCpu_f, &table_buffer, 0);
        cmd = DRV_IOW(IpeLegacyCFHeaderXlateCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));

        sal_memset(&table_buffer, 0, sizeof(EpeLegacyCFHeaderXlateCtl_m));
        if (DRV_FROM_TMM(lchip))
        {
            SetEpeLegacyCFHeaderXlateCtl(V, c2cQueSelType_f, &table_buffer, 6);
            SetEpeLegacyCFHeaderXlateCtl(V, fromCpuQueSelType_f, &table_buffer, 3);
            SetEpeLegacyCFHeaderXlateCtl(V, spanQueSelType_f, &table_buffer, 4);
            SetEpeLegacyCFHeaderXlateCtl(V, toCpuQueSelType_f, &table_buffer, 1);
        }
        else
        {
            SetEpeLegacyCFHeaderXlateCtl(V, g_0_queSelType_f, &table_buffer, 0);
            SetEpeLegacyCFHeaderXlateCtl(V, g_1_queSelType_f, &table_buffer, 6);
        }
        cmd = DRV_IOW(EpeLegacyCFHeaderXlateCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));
    }


    sal_memset(&table_buffer, 0, sizeof(IpeFwdCflexUplinkLagHashCtl_m));
    cmd = DRV_IOR(IpeFwdCflexUplinkLagHashCtl_t, DRV_ENTRY_FLAG);
    if (CTC_STACKING_VERSION_2_0 == p_glb_cfg->version)
    {
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_0_destMapMask_f, &table_buffer, 0x7FFFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_0_sourcePortMask_f, &table_buffer, 0xFFFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_0_headerHashMask_f, &table_buffer, 0xFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_1_destMapMask_f, &table_buffer, 0x7FFFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_1_sourcePortMask_f, &table_buffer, 0xFFFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_1_headerHashMask_f, &table_buffer, 0xFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_2_destMapMask_f, &table_buffer, 0x7FFFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_2_sourcePortMask_f, &table_buffer, 0xFFFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, gFwdType_2_headerHashMask_f, &table_buffer, 0xFF);
        SetIpeFwdCflexUplinkLagHashCtl(V, backToHeadHash_f, &table_buffer, 0);
        SetIpeFwdCflexUplinkLagHashCtl(V, srcPortModeFabric_f, &table_buffer, 1);

    }
    else if(CTC_STACKING_VERSION_1_0 == p_glb_cfg->version)
    {
        SetIpeFwdCflexUplinkLagHashCtl(V, cflexHashTypeFabric_f, &table_buffer, 0);
        SetIpeFwdCflexUplinkLagHashCtl(V, backToHeadHash_f, &table_buffer, 1);
    }

    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_0_destMapMask_f, &table_buffer, 0x7FFFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_0_sourcePortMask_f, &table_buffer, 0xFFFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_0_headerHashMask_f, &table_buffer, 0xFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_1_destMapMask_f, &table_buffer, 0x7FFFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_1_sourcePortMask_f, &table_buffer, 0xFFFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_1_headerHashMask_f, &table_buffer, 0xFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_2_destMapMask_f, &table_buffer, 0x7FFFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_2_sourcePortMask_f, &table_buffer, 0xFFFF);
    SetIpeFwdCflexUplinkLagHashCtl(V, gFwdTypeFabric_2_headerHashMask_f, &table_buffer, 0xFF);
    /* cflexHashTypeFabric:
    0: HEAD HASH
    1: FLOW_HASH
    2: CRC8
    3: XOR8
	*/
    SetIpeFwdCflexUplinkLagHashCtl(V, cflexHashTypeFabric_f, &table_buffer, 2);
    SetIpeFwdCflexUplinkLagHashCtl(V, cflexHashType_f, &table_buffer, (SYS_STACKING_SRC_PORT_MODE_HASH == p_glb_cfg->src_port_mode)?1:0);
    SetIpeFwdCflexUplinkLagHashCtl(V, backToHeaderHash_f, &table_buffer, 1);
    /*default use linkagg gchip to cal hash*/
    SetIpeFwdCflexUplinkLagHashCtl(V, cflexLagSrcPortMode_f, &table_buffer, 1);
    cmd = DRV_IOW(IpeFwdCflexUplinkLagHashCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &table_buffer));


    field_val = (CTC_STACKING_VERSION_2_0 == p_glb_cfg->version)?1:0;
    cmd = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_cflexGlbDestPortEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    /*Disable lchip global port map*/
    sal_memset(&table_buffer, 0, sizeof(DsGlbDestPortMap_m));
    SetDsGlbDestPortMap(V, glbDestPortBase_f, &table_buffer, 0);
    SetDsGlbDestPortMap(V, glbDestPortMin_f, &table_buffer, 1);
    SetDsGlbDestPortMap(V, glbDestPortMax_f, &table_buffer, 0);

    cmd = DRV_IOW(DsGlbDestPortMap_t, DRV_ENTRY_FLAG);

    for (gchip_id = 0; gchip_id < SYS_STK_MAX_GCHIP; gchip_id++)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, gchip_id, cmd, &table_buffer));
    }

    CTC_ERROR_RETURN(_sys_usw_stacking_set_learning_mode(lchip, p_glb_cfg->learning_mode));

    /*mapping trunk and rr profile id*/
    for (index = 0; index < CTC_CONST16; index++)
    {
        value = index;
        cmd = DRV_IOW(ChanLagRrProfileIdMappingCtl_t, ChanLagRrProfileIdMappingCtl_chanRrProfileId_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, (index+1), cmd, &value));
    }

    if (DRV_FROM_AT(lchip))
    {
        /*mox need vrf to remote chip*/
        if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_IPFIX))
        {
            value = 1;
            cmd = DRV_IOW(EpeHeaderEditXCtl_t, EpeHeaderEditXCtl_cflexXCFVrfIdEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

            cmd = DRV_IOW(IpeHeaderAdjustXCtl_t, IpeHeaderAdjustXCtl_cflexXCFVrfIdEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

            cmd = DRV_IOW(IpeLookupCtl_t, IpeLookupCtl_vrfIdValidFromCFHeader_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

            /*xData 32~48 for vrfid*/
            value = 2;
            cmd = DRV_IOW(EpeHeaderEditXCtl_t, EpeHeaderEditXCtl_cflexXCFVrfIdSel_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

            cmd = DRV_IOW(IpeHeaderAdjustXCtl_t, IpeHeaderAdjustXCtl_cflexXCFVrfIdSel_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
        }
        value = 0xFF;

        cmd = DRV_IOW(EpeHeaderEditXCtl_t, EpeHeaderEditXCtl_xCFHeaderEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }
    return CTC_E_NONE;
}

uint32
_sys_usw_stacking_mcast_hash_make(sys_stacking_mcast_db_t* backet)
{
    uint32 val = 0;
    uint8* data = NULL;
    uint8   length = 0;


    if (!backet)
    {
        return 0;
    }

    val = (backet->type << 24) | (backet->id);

    data = (uint8*)&val;
    length = sizeof(uint32);

    return ctc_hash_caculate(length, data);
}

/**
 @brief  hash comparison hook.
*/
bool
_sys_usw_stacking_mcast_hash_cmp(sys_stacking_mcast_db_t* backet1,
                                sys_stacking_mcast_db_t* backet2)
{

    if (!backet1 || !backet2)
    {
        return FALSE;
    }

    if ((backet1->type == backet2->type) &&
        (backet1->id == backet2->id))
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_stacking_mcast_group_create(uint8 lchip,
                                           uint8 type,
                                           uint16 id,
                                           sys_stacking_mcast_db_t **pp_mcast_db,
                                           uint8 append_en)
{
    int32  ret                     = CTC_E_NONE;
    uint32 new_met_offset          = 0;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;
    sys_nh_param_dsmet_t dsmet_para;


    /*build node*/
    p_mcast_db = (sys_stacking_mcast_db_t*)mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_mcast_db_t));
    if (NULL == p_mcast_db)
    {
        ret =  CTC_E_NO_MEMORY;
        goto Error0;
    }

    sal_memset(p_mcast_db, 0, sizeof(sys_stacking_mcast_db_t));
    p_mcast_db->type = type;
    p_mcast_db->id   = id;

    if (append_en)
    {
        p_mcast_db->last_tail_offset = g_stacking_master[lchip]->stacking_mcast_offset;
    }
    else
    {
        p_mcast_db->last_tail_offset = SYS_NH_INVALID_OFFSET;
    }

    sal_memset(&dsmet_para, 0, sizeof(sys_nh_param_dsmet_t));
    dsmet_para.next_met_entry_ptr = SYS_NH_NEXT_MET_ENTRY(lchip, p_mcast_db->last_tail_offset);

    if (type == 0) /* mcast profile */
    {
        /*alloc resource*/
        CTC_ERROR_GOTO(sys_usw_nh_alloc(lchip, SYS_API_NH_DSMET_RSVED, 1, &new_met_offset),
                       ret, Error1);

        dsmet_para.met_offset = new_met_offset;
        dsmet_para.dest_id = 0 ;
        dsmet_para.remote_chip = 1;
        CTC_ERROR_GOTO(sys_usw_nh_add_dsmet(lchip, &dsmet_para, 0), ret, Error2);
        /*add db*/
        p_mcast_db->head_met_offset = new_met_offset;
        p_mcast_db->tail_met_offset = p_mcast_db->last_tail_offset;
        p_mcast_db->append_en = append_en;
    }
    else/* keeplive */
    {
        new_met_offset = id;

        dsmet_para.met_offset = new_met_offset;
        dsmet_para.dest_id = SYS_RSV_PORT_DROP_ID ;
        dsmet_para.end_local_rep = 1;
        CTC_ERROR_GOTO(sys_usw_nh_add_dsmet(lchip, &dsmet_para, 0), ret, Error1);

        /*add db, for keepalive group must reserve 1st met for CPU port, tail_met_offset cannot equal last_tail_offset when create*/
        p_mcast_db->head_met_offset = new_met_offset;
        p_mcast_db->tail_met_offset = new_met_offset;
    }

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "head_met_offset :%d\n ", new_met_offset);
    if(NULL == ctc_hash_insert(g_stacking_master[lchip]->mcast_hash, p_mcast_db))
    {
        ret = CTC_E_NO_MEMORY;
        goto Error2;
    }

    *pp_mcast_db = p_mcast_db;

    return CTC_E_NONE;


    Error2:

    if (type == 0)
    {
        sys_usw_nh_free(lchip, SYS_API_NH_DSMET_RSVED, 1, new_met_offset);
    }

    Error1:

    if (p_mcast_db)
    {
        mem_free(p_mcast_db);
    }

    Error0:

    return ret;

}

STATIC int32
_sys_usw_stacking_mcast_group_destroy(uint8 lchip,
                                            uint8 type,
                                            uint16 id,
                                            sys_stacking_mcast_db_t *p_mcast_db)
{
    sys_nh_param_dsmet_t dsmet;
    uint32 met_offset = 0;

    met_offset = p_mcast_db->head_met_offset;
    /* keep live head met offset do not need free*/
    while(met_offset != 0xffff)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_dsmet(lchip, met_offset, &dsmet));
        met_offset = dsmet.next_met_entry_ptr;
        if(met_offset == g_stacking_master[lchip]->p_default_prof_db->head_met_offset)
        {
            break;
        }
        if(met_offset != 0xffff)
        {
            CTC_ERROR_RETURN(sys_usw_nh_free(lchip, SYS_API_NH_DSMET_RSVED, 1, met_offset));
        }
    }

    sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
    dsmet.next_met_entry_ptr = SYS_NH_INVALID_OFFSET;
    dsmet.dest_id = 0 ;
    dsmet.remote_chip = 1;
    dsmet.met_offset = p_mcast_db->head_met_offset;
    CTC_ERROR_RETURN(sys_usw_nh_add_dsmet(lchip, &dsmet, 0));

    if (type == 0)/* mcast profile */
    {
        /*free resource*/
        CTC_ERROR_RETURN(sys_usw_nh_free(lchip, SYS_API_NH_DSMET_RSVED, 1, p_mcast_db->head_met_offset));
    }

    ctc_hash_remove(g_stacking_master[lchip]->mcast_hash, p_mcast_db);

    mem_free(p_mcast_db);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_mcast_group_add_member(uint8 lchip,
                                               sys_stacking_mcast_db_t *p_mcast_db,
                                               uint16 dest_id, uint8 is_remote)
{
    int32  ret                     = CTC_E_NONE;
    uint32 new_met_offset          = 0;
    sys_nh_param_dsmet_t dsmet;
    uint32 dsnh_offset             = 0;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "dest_id = %d, head:%d, is_remote:%u \n", dest_id, p_mcast_db->head_met_offset, is_remote);

    if (!is_remote)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH, &dsnh_offset));
    }

    if (p_mcast_db->tail_met_offset == p_mcast_db->last_tail_offset)
    {

        sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
        dsmet.next_met_entry_ptr = SYS_NH_NEXT_MET_ENTRY(lchip, p_mcast_db->last_tail_offset);
        dsmet.dest_id = dest_id ;
        dsmet.remote_chip = is_remote;
        dsmet.met_offset = p_mcast_db->head_met_offset;
        dsmet.next_hop_ptr = dsnh_offset;
        CTC_ERROR_RETURN(sys_usw_nh_add_dsmet(lchip, &dsmet, 0));

        p_mcast_db->tail_met_offset = p_mcast_db->head_met_offset;

        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update head_met_offset :%d, trunk-id:%d \n ", new_met_offset, dest_id);

    }
    else
    {

        /*new mcast offset*/
        CTC_ERROR_RETURN(sys_usw_nh_alloc(lchip, SYS_API_NH_DSMET_RSVED, 1, &new_met_offset));
        sal_memset(&dsmet, 0, sizeof(dsmet));
        dsmet.next_met_entry_ptr = SYS_NH_NEXT_MET_ENTRY(lchip, p_mcast_db->last_tail_offset);
        dsmet.dest_id = dest_id ;
        dsmet.remote_chip = is_remote;
        dsmet.met_offset = new_met_offset;
        dsmet.next_hop_ptr = dsnh_offset;
        CTC_ERROR_GOTO(sys_usw_nh_add_dsmet(lchip, &dsmet, 0),ret, Error0);

        sal_memset(&dsmet, 0, sizeof(dsmet));
        dsmet.next_met_entry_ptr = new_met_offset;
        dsmet.next_met_entry_ptr_valid = 1;
        CTC_ERROR_GOTO(sys_usw_nh_update_dsmet(lchip, p_mcast_db->tail_met_offset,
                                                   &dsmet),ret, Error0);

        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "add new_met_offset :%d, pre_offset:%d, dest_id:%d\n ", new_met_offset,
                                              p_mcast_db->tail_met_offset, dest_id);

        p_mcast_db->tail_met_offset = new_met_offset;

    }

    if (is_remote)
    {
        CTC_BIT_SET(p_mcast_db->trunk_bitmap[dest_id / 32], dest_id % 32);
    }
    return CTC_E_NONE;

    Error0:
    sys_usw_nh_free(lchip, SYS_API_NH_DSMET_RSVED, 1, new_met_offset);

    return ret;


}

STATIC int32
_sys_usw_stacking_mcast_group_remove_member(uint8 lchip,
                                                  sys_stacking_mcast_db_t *p_mcast_db,
                                                  uint16 dest_id, uint8 is_remote)
{
    uint32 head_met_offset         = 0;
    uint32 pre_met_offset          = 0;
    uint32 cur_met_offset          = 0;
    uint32 next_met_offset         = 0;
    sys_nh_param_dsmet_t dsmet;
    uint8   is_found               = 0;


    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "dest_id = %d, head:%d, is_remote:%u \n", dest_id, p_mcast_db->head_met_offset, is_remote);

    head_met_offset = p_mcast_db->head_met_offset;
    cur_met_offset  = head_met_offset;
    next_met_offset = head_met_offset;


    do
    {
        pre_met_offset = cur_met_offset;
        cur_met_offset = next_met_offset;
        CTC_ERROR_RETURN(sys_usw_nh_get_dsmet(lchip, cur_met_offset, &dsmet));
        next_met_offset = dsmet.next_met_entry_ptr;
        if ((dsmet.remote_chip == is_remote) && (dsmet.dest_id== dest_id))
        {
            is_found = 1;
            break;
        }

    }
    while (next_met_offset != p_mcast_db->last_tail_offset);

    if (!is_found)
    {
        return  CTC_E_ENTRY_NOT_EXIST;
    }

    if (cur_met_offset == head_met_offset)
    {
        /*remove is first met*/
        if (next_met_offset == p_mcast_db->last_tail_offset)
        {
            /*remove last node, */
            sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
            dsmet.next_met_entry_ptr = SYS_NH_NEXT_MET_ENTRY(lchip, p_mcast_db->last_tail_offset);
            dsmet.dest_id = 0 ;
            dsmet.remote_chip = 1;
            dsmet.met_offset = head_met_offset;
            CTC_ERROR_RETURN(sys_usw_nh_add_dsmet(lchip, &dsmet, 0));

            p_mcast_db->tail_met_offset = p_mcast_db->last_tail_offset;

            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Update first to drop, head_met_offset: %d, dest_id:%d, is_remote:%u\n ",
                            head_met_offset, dest_id, is_remote);

            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tail:%d\n ",  p_mcast_db->tail_met_offset);
        }
        else
        {
            uint32 cmd                     = 0;
            uint32 tbl_id = DRV_FROM_AT(lchip)?
                   (DRV_TABLE_MAX_INDEX(lchip, DsMetEntrySlim1X_t)? DsMetEntrySlim1X_t : DsMetEntry1X_t) : DsMetEntry3W_t;
            ds_t ds;

            /*free currect offset*/
            CTC_ERROR_RETURN(sys_usw_nh_free(lchip, SYS_API_NH_DSMET_RSVED, 1, next_met_offset));

            /*nexthop change to first*/
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN( DRV_IOCTL(lchip, next_met_offset, cmd, &ds));

            /*nexthop change to first*/
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, cur_met_offset, cmd, &ds));


            if (p_mcast_db->tail_met_offset == next_met_offset)
            {
                p_mcast_db->tail_met_offset = cur_met_offset;
            }


            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Replace first head_met_offset: %d, dest_id:%d, is_remote:%u\n ",
                            head_met_offset, dest_id, is_remote);

            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Free Met offset:%d, tail:%d\n ",  next_met_offset, p_mcast_db->tail_met_offset);

        }
    }
    else
    {
        /*free currect offset*/
        CTC_ERROR_RETURN(sys_usw_nh_free(lchip, SYS_API_NH_DSMET_RSVED, 1, cur_met_offset));

        sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
        dsmet.next_met_entry_ptr = next_met_offset;
        dsmet.next_met_entry_ptr_valid = 1;
        CTC_ERROR_RETURN(sys_usw_nh_update_dsmet(lchip, pre_met_offset, &dsmet));

        if (p_mcast_db->tail_met_offset == cur_met_offset)
        {
            p_mcast_db->tail_met_offset = pre_met_offset;
        }

        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Remove middle pre: %d, cur:%d, next:%d, dest_id:%d\n ",
                        pre_met_offset, cur_met_offset, next_met_offset,  dest_id);

        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Free Met offset:%d, tail:%d\n ",  cur_met_offset, p_mcast_db->tail_met_offset);
    }

    if (is_remote)
    {
        CTC_BIT_UNSET(p_mcast_db->trunk_bitmap[dest_id / 32], dest_id % 32);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_mcast_group_set_member_with_nh(uint8 lchip, sys_stacking_mcast_db_t *p_mcast_db, uint32 nh_id, uint8 is_add)
{
    uint32 met_offset = 0;
    uint32 next_met_offset = 0;
    sys_nh_param_dsmet_t dsmet;
    ds_t ds;
    if ((g_stacking_master[lchip]->mcast_mode != 1) || (p_mcast_db->append_en))
    {
        return CTC_E_INVALID_CONFIG;
    }

    sal_memset(&ds, 0, sizeof(ds));
    sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
    
    if (0 == p_mcast_db->type)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_mcast_profile_offset(lchip, nh_id, &next_met_offset));
    }
    else
    {
        sys_stacking_mcast_db_t tmp_mcast_db;
        sys_stacking_mcast_db_t* p_tmp_mcast_db = NULL; 
        sal_memset(&tmp_mcast_db, 0, sizeof(tmp_mcast_db));
        tmp_mcast_db.type = 0;
        tmp_mcast_db.id   = nh_id;
        p_tmp_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &tmp_mcast_db);

        if (NULL == p_tmp_mcast_db)
        {
            return CTC_E_NOT_EXIST;
        }
        next_met_offset = p_tmp_mcast_db->head_met_offset;
    }

    if (is_add)
    {
        if (next_met_offset == p_mcast_db->last_tail_offset)
        {
            return CTC_E_EXIST;
        }        
    }
    else
    {
        if (next_met_offset != p_mcast_db->last_tail_offset)
        {
            return CTC_E_NOT_EXIST;
        }
        next_met_offset = SYS_NH_INVALID_OFFSET;
    }
    met_offset = (p_mcast_db->tail_met_offset == p_mcast_db->last_tail_offset)? p_mcast_db->head_met_offset : p_mcast_db->tail_met_offset;
    
    dsmet.next_met_entry_ptr = next_met_offset;
    dsmet.next_met_entry_ptr_valid = 1;
    CTC_ERROR_RETURN(sys_usw_nh_update_dsmet(lchip, met_offset, &dsmet));
    
    if (p_mcast_db->tail_met_offset == p_mcast_db->last_tail_offset)
    {
        p_mcast_db->tail_met_offset = next_met_offset;
    }
    p_mcast_db->last_tail_offset = next_met_offset;

    return CTC_E_NONE;                                              
}

STATIC int32
_sys_usw_stacking_encap_header_enable(uint8 lchip, uint16 chan_id, ctc_stacking_hdr_encap_t* p_encap, uint8 dir)
{
    uint32 cmd                     = 0;
    uint8 mux_type                 = 0;
    uint32 field_val               = 0;
    uint8 out_encap_type           = 0;
    hw_mac_addr_t mac;
    DsPacketHeaderEditTunnel_m  ds_packet_header_edit_tunnel;
    uint16 lport = 0;
    uint8 cld_hdr_len = 0;
    uint8 udp_en = 0;
    uint32 hdr_flag = 0;

    cmd = DRV_IOR(IpeHeaderAdjustCtl_t, IpeHeaderAdjustCtl_headerUdpEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    udp_en = field_val;

    hdr_flag = (NULL == p_encap)?CTC_STK_HDR_WITH_NONE: p_encap->hdr_flag;
    switch (hdr_flag)
    {
    case CTC_STK_HDR_WITH_NONE:
        mux_type = DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITHOUT_TUNNEL);
        out_encap_type = SYS_STK_OUT_ENCAP_NONE;
        break;

    case CTC_STK_HDR_WITH_L2:
        mux_type = DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2);
        out_encap_type = SYS_STK_OUT_ENCAP_NONE;
        cld_hdr_len = 14;
        break;

    case CTC_STK_HDR_WITH_L2_AND_IPV4:
        if (!DRV_IS_DUET2(lchip))
        {
            return CTC_E_NOT_SUPPORT;
        }
        mux_type = DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2_AND_IPV4);
        out_encap_type = SYS_STK_OUT_ENCAP_IPV4;
        cld_hdr_len = 14 + (udp_en?28:20);
        break;

    case CTC_STK_HDR_WITH_L2_AND_IPV6:
        if (!DRV_IS_DUET2(lchip))
        {
            return CTC_E_NOT_SUPPORT;
        }

        mux_type = DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2_AND_IPV6);
        out_encap_type = SYS_STK_OUT_ENCAP_IPV6;
        cld_hdr_len = 14 + (udp_en?48:40);
        break;

    case CTC_STK_HDR_WITH_IPV4:
        if (!DRV_IS_DUET2(lchip))
        {
            return CTC_E_NOT_SUPPORT;
        }

        mux_type = DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_IPV4);
        out_encap_type = SYS_STK_OUT_ENCAP_IPV4;
        cld_hdr_len = (udp_en?28:20);
        break;

    case CTC_STK_HDR_WITH_IPV6:
        if (!DRV_IS_DUET2(lchip))
        {
            return CTC_E_NOT_SUPPORT;
        }

        mux_type = DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_IPV6);
        out_encap_type = SYS_STK_OUT_ENCAP_IPV6;
        cld_hdr_len = (udp_en?48:40);
        break;

    default:
        return CTC_E_INVALID_PARAM;
    }

    if ((dir == CTC_INGRESS) || (dir == CTC_BOTH_DIRECTION))
    {
        /*mux type*/
        cmd = DRV_IOW(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_muxType_f);
        field_val = mux_type;
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
    }

    if ((dir == CTC_EGRESS) || (dir == CTC_BOTH_DIRECTION))
    {
        uint16 chan_tmp = SYS_USW_CHANNEL_ENCODE(chan_id);
        EpeHdrAdjustChanCtl_m    epe_hdr_adjust_chan_ctl;
        BufRetrvChanStackingEn_m stacking_en;
        BufRetrvDPChanStackingEn_m stacking_en1;
        uint32 packet_header_en[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};

        sal_memset(&ds_packet_header_edit_tunnel, 0, sizeof(ds_packet_header_edit_tunnel));
        cmd = DRV_IOR(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_adjust_chan_ctl) );
        GetEpeHdrAdjustChanCtl(A, packetHeaderEn_f, &epe_hdr_adjust_chan_ctl, packet_header_en);
        CTC_BIT_SET(packet_header_en[chan_tmp>>5], chan_tmp&0x1F);
        SetEpeHdrAdjustChanCtl(A, packetHeaderEn_f, &epe_hdr_adjust_chan_ctl, packet_header_en);
        cmd = DRV_IOW(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_adjust_chan_ctl) );

        sal_memset(&stacking_en, 0, sizeof(stacking_en));
        sal_memset(packet_header_en, 0, sizeof(packet_header_en));

        if (DRV_FROM_TMM(lchip))
        {
            cmd = DRV_IOR(BufRetrvDPChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id/MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM), cmd, &stacking_en1) );
            GetBufRetrvDPChanStackingEn(A, chanStackingEn_f, &stacking_en1, packet_header_en);
            CTC_BIT_SET(packet_header_en[(chan_id % MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM)) >> 5], chan_id&0x1F);
            SetBufRetrvDPChanStackingEn(A, chanStackingEn_f, &stacking_en1, packet_header_en);
            cmd = DRV_IOW(BufRetrvDPChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id/MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM), cmd, &stacking_en1) );
        }
        else
        {
            cmd = DRV_IOR(BufRetrvChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &stacking_en) );
            GetBufRetrvChanStackingEn(A, chanStackingEn_f, &stacking_en, packet_header_en);
            CTC_BIT_SET(packet_header_en[chan_id >> 5], chan_id&0x1F);
            SetBufRetrvChanStackingEn(A, chanStackingEn_f, &stacking_en, packet_header_en);
            cmd = DRV_IOW(BufRetrvChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &stacking_en) );
        }

        if (DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2) == mux_type ||
            DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2_AND_IPV4) == mux_type ||
            DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2_AND_IPV6) == mux_type)
        {
            SetDsPacketHeaderEditTunnel(V, packetHeaderL2En_f , &ds_packet_header_edit_tunnel, 1);
            SetDsPacketHeaderEditTunnel(V, vlanIdValid_f, &ds_packet_header_edit_tunnel, p_encap->vlan_valid);

            if (p_encap->vlan_valid)
            {
                SetDsPacketHeaderEditTunnel(V, vlanId_f , &ds_packet_header_edit_tunnel, p_encap->vlan_id);
                cld_hdr_len += 4;
            }

            SYS_USW_SET_HW_MAC(mac, p_encap->mac_da)
            SetDsPacketHeaderEditTunnel(A, macDa_f, &ds_packet_header_edit_tunnel, mac);
            SYS_USW_SET_HW_MAC(mac, p_encap->mac_sa)
            SetDsPacketHeaderEditTunnel(A, macSa_f , &ds_packet_header_edit_tunnel, mac);
        }
        SetDsPacketHeaderEditTunnel(V, packetHeaderL3Type_f , &ds_packet_header_edit_tunnel, out_encap_type);

        if (SYS_STK_OUT_ENCAP_IPV4 == out_encap_type)
        {
            SetDsPacketHeaderEditTunnel(A, ipDa_f  , &ds_packet_header_edit_tunnel, &p_encap->ipda.ipv4);
        }

        if (SYS_STK_OUT_ENCAP_IPV6 == out_encap_type)
        {
            uint32 ipv6_da[CTC_IPV6_ADDR_LEN];
            /* ipda, use little india for DRV_SET_FIELD_A */
            ipv6_da[0] = p_encap->ipda.ipv6[3];
            ipv6_da[1] = p_encap->ipda.ipv6[2];
            ipv6_da[2] = p_encap->ipda.ipv6[1];
            ipv6_da[3] = p_encap->ipda.ipv6[0];
            SetDsPacketHeaderEditTunnel(A, ipDa_f  , &ds_packet_header_edit_tunnel, &ipv6_da);
        }

        cmd = DRV_IOW(DsPacketHeaderEditTunnel_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ds_packet_header_edit_tunnel));
    }

    lport = SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, chan_id);
    CTC_ERROR_RETURN(sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_CLD_HDR_LEN, lport, cld_hdr_len));

    return CTC_E_NONE;
}

int32
_sys_usw_stacking_encap_header_disable(uint8 lchip, uint16 chan_id, uint8 dir)
{
    uint32 cmd                     = 0;
    uint8 mux_type                 = 0;
    uint32 field_val               = 0;
    uint16 lport = 0;

    DsPacketHeaderEditTunnel_m  ds_packet_header_edit_tunnel;

    mux_type = DRV_ENUM(DRV_STK_MUX_TYPE_HDR_REGULAR_PORT);

    if ((dir == CTC_INGRESS) || (dir == CTC_BOTH_DIRECTION))
    {
        /*mux type*/
        cmd = DRV_IOW(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_muxType_f);
        field_val = mux_type;
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));

        lport = SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, chan_id);
        CTC_ERROR_RETURN(sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_CLD_HDR_LEN, lport, 0xff));
    }

    if ((dir == CTC_EGRESS) || (dir == CTC_BOTH_DIRECTION))
    {
        uint16 chan_tmp = SYS_USW_CHANNEL_ENCODE(chan_id);
        EpeHdrAdjustChanCtl_m    epe_hdr_adjust_chan_ctl;
        BufRetrvChanStackingEn_m stacking_en;
        BufRetrvDPChanStackingEn_m stacking_en1;
        uint32 packet_header_en[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};

        sal_memset(&ds_packet_header_edit_tunnel, 0, sizeof(ds_packet_header_edit_tunnel));
        cmd = DRV_IOW(DsPacketHeaderEditTunnel_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ds_packet_header_edit_tunnel));

        sal_memset(packet_header_en, 0, sizeof(packet_header_en));
        cmd = DRV_IOR(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_adjust_chan_ctl) );
        GetEpeHdrAdjustChanCtl(A, packetHeaderEn_f, &epe_hdr_adjust_chan_ctl, packet_header_en);
        CTC_BIT_UNSET(packet_header_en[chan_tmp >> 5], chan_tmp&0x1F);
        SetEpeHdrAdjustChanCtl(A, packetHeaderEn_f, &epe_hdr_adjust_chan_ctl, packet_header_en);
        cmd = DRV_IOW(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_adjust_chan_ctl) );

        sal_memset(&stacking_en, 0, sizeof(stacking_en));
        sal_memset(packet_header_en, 0, sizeof(packet_header_en));

        if (DRV_FROM_TMM(lchip))
        {
            cmd = DRV_IOR(BufRetrvDPChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id / MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM), cmd, &stacking_en1) );
            GetBufRetrvDPChanStackingEn(A, chanStackingEn_f, &stacking_en1, packet_header_en);
            CTC_BIT_UNSET(packet_header_en[(chan_id % MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM)) >> 5], chan_id&0x1F);
            SetBufRetrvDPChanStackingEn(A, chanStackingEn_f, &stacking_en1, packet_header_en);
            cmd = DRV_IOW(BufRetrvDPChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id / MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM), cmd, &stacking_en1) );
        }
        else
        {
            cmd = DRV_IOR(BufRetrvChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &stacking_en) );
            GetBufRetrvChanStackingEn(A, chanStackingEn_f, &stacking_en, packet_header_en);
            CTC_BIT_UNSET(packet_header_en[chan_id >> 5], chan_id&0x1F);
            SetBufRetrvChanStackingEn(A, chanStackingEn_f, &stacking_en, packet_header_en);
            cmd = DRV_IOW(BufRetrvChanStackingEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &stacking_en) );
        }
    }

    return CTC_E_NONE;
}

STATIC uint8
_sys_usw_stacking_is_trunk_have_member(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 packet_header_en[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    uint32 zero[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    EpeHdrAdjustChanCtl_m epe_hdr_adjust_chan_ctl;

    cmd = DRV_IOR(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_adjust_chan_ctl));

    GetEpeHdrAdjustChanCtl(A, packetHeaderEn_f, &epe_hdr_adjust_chan_ctl, packet_header_en);
    if (sal_memcmp(packet_header_en, zero, sizeof(zero)))
    {
        return 1;
    }

    return 0;
}

STATIC int32
_sys_usw_stacking_all_mcast_add_default_profile(void* bucket_data, void* user_data)
{
    uint8 lchip = *((uint8*) user_data);
    uint32 cur_met_offset          = 0;
    uint32 next_met_offset         = 0;
    sys_nh_param_dsmet_t dsmet;
    sys_nh_info_mcast_t* p_mcast_db = NULL;
    if(((sys_nh_info_com_t*)bucket_data)->hdr.nh_entry_type != SYS_NH_TYPE_MCAST)
    {
       return CTC_E_NONE;
    }
    p_mcast_db = (sys_nh_info_mcast_t*)bucket_data;
    next_met_offset = p_mcast_db->basic_met_offset;

    do
    {
        cur_met_offset = next_met_offset;
        CTC_ERROR_RETURN(sys_usw_nh_get_dsmet(lchip, cur_met_offset, &dsmet));
        next_met_offset = dsmet.next_met_entry_ptr;
        if (next_met_offset == g_stacking_master[lchip]->stacking_mcast_offset)
        {
           goto done;
        }

    }
    while (next_met_offset != SYS_NH_INVALID_OFFSET);
    sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
    dsmet.next_met_entry_ptr = SYS_NH_NEXT_MET_ENTRY(lchip, g_stacking_master[lchip]->stacking_mcast_offset);
    dsmet.next_met_entry_ptr_valid = 1;
    CTC_ERROR_RETURN(sys_usw_nh_update_dsmet(lchip, cur_met_offset, &dsmet));

done:
    if (!CTC_FLAG_ISSET(p_mcast_db->mcast_flag, SYS_NH_INFO_MCAST_FLAG_MEM_PROFILE)
        && !CTC_FLAG_ISSET(p_mcast_db->mcast_flag, SYS_NH_INFO_MCAST_FLAG_STK_MEM_PROFILE))
    {
        p_mcast_db->profile_met_offset = g_stacking_master[lchip]->stacking_mcast_offset;
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_stacking_all_mcast_remove_default_profile(void* bucket_data, void* user_data)
{   
    uint8 lchip = *((uint8*) user_data);
    uint32 cur_met_offset          = 0;
    uint32 next_met_offset         = 0;
    sys_nh_param_dsmet_t dsmet;
    sys_nh_info_mcast_t* p_mcast_db = NULL;
    if(((sys_nh_info_com_t*)bucket_data)->hdr.nh_entry_type != SYS_NH_TYPE_MCAST)
    {
       return CTC_E_NONE;
    }
    p_mcast_db = (sys_nh_info_mcast_t*)bucket_data;
    next_met_offset = p_mcast_db->basic_met_offset;

    do
    {
        cur_met_offset = next_met_offset;
        CTC_ERROR_RETURN(sys_usw_nh_get_dsmet(lchip, cur_met_offset, &dsmet));
        next_met_offset = dsmet.next_met_entry_ptr;
        if (next_met_offset == g_stacking_master[lchip]->stacking_mcast_offset)
        {
            break;
        }

    }
    while (next_met_offset != SYS_NH_INVALID_OFFSET);

    if (next_met_offset !=  g_stacking_master[lchip]->stacking_mcast_offset)
    {
        return CTC_E_NONE;
    }
    sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
    dsmet.next_met_entry_ptr = SYS_NH_INVALID_OFFSET;
    dsmet.next_met_entry_ptr_valid = 1;
    CTC_ERROR_RETURN(sys_usw_nh_update_dsmet(lchip, cur_met_offset, &dsmet));
    if (!CTC_FLAG_ISSET(p_mcast_db->mcast_flag, SYS_NH_INFO_MCAST_FLAG_MEM_PROFILE)
        && !CTC_FLAG_ISSET(p_mcast_db->mcast_flag, SYS_NH_INFO_MCAST_FLAG_STK_MEM_PROFILE))
    {
        p_mcast_db->profile_met_offset = 0;
    }
    return CTC_E_NONE;
}



int32
_sys_usw_stacking_all_mcast_bind_en(uint8 lchip, uint8 enable)
{
    hash_traversal_fn fn = NULL;

    SYS_STK_INIT_CHECK(lchip);

    if (enable)
    {
        fn = _sys_usw_stacking_all_mcast_add_default_profile;
    }
    else
    {
        fn = _sys_usw_stacking_all_mcast_remove_default_profile;
    }

    sys_usw_nh_traverse_nh_db(lchip, fn, &lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER, 1);
    g_stacking_master[lchip]->bind_mcast_en = enable?1:0;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_set_stacking_port_en(uint8 lchip, sys_stacking_trunk_info_t* p_trunk, ctc_stacking_hdr_encap_t* p_encap_hdr, uint32 gport, uint8 enable)
{
    /*EpeHdrAdjustChanCtl_m    epe_hdr_adjust_chan_ctl;
    BufRetrvChanStackingEn_m stacking_en;

    uint32 packet_header_en[8] = {0};*/
    uint32 sniffing_bitmap[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    EpeHdrEditSniffingCtl_m epe_hdr_edit_sniffing_ctl;
    uint32 field_val;
    uint32 cmd;
    uint16 lport;
    uint32 rx_chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
    uint32 tx_chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
    /*uint8 enq_mode = 0;
    int32 ret = 0;*/
    uint32 ingr_en = 0;
    uint32 egr_en = 0;
    uint8  rx_chan_num = 0;
    uint8  tx_chan_num = 0;
    uint8  index  = 0;
    uint8 enq_mode = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    EpeScheduleTruncateCheckCfg_m epe_sch_trun_cfg;
    uint32 mac_id = 0;
    int32 ret = 0;
    sys_usw_queue_get_enq_mode(lchip, &enq_mode);
    if (!((DRV_IS_DUET2(lchip) && (1 == enq_mode)) || DRV_FROM_AT(lchip)))
    {
        if (enable)
        {
            ret = sys_usw_queue_add_for_stacking(lchip, gport);
        }
        else
        {
            ret = sys_usw_queue_remove_for_stacking(lchip, gport);
        }
        if (ret != CTC_E_NONE && ret != CTC_E_EXIST)
        {
            return ret;
        }
    }

    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 1, gport, rx_chan_id, &rx_chan_num));
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 0, gport, tx_chan_id, &tx_chan_num));
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER, 1);
    lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport);
    field_val = enable? (g_stacking_master[lchip]->fabric_mode?1:2) : 0;
    sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_CFLEX_MODE, lport,  field_val);

    cmd = DRV_IOR(EpeHdrEditSniffingCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_edit_sniffing_ctl));
    GetEpeHdrEditSniffingCtl(A, sniffingPacketTxEn_f,  &epe_hdr_edit_sniffing_ctl, sniffing_bitmap);
    for (index = 0; index < rx_chan_num; index++)
    {
        uint16 channel_id = SYS_USW_CHANNEL_ENCODE(rx_chan_id[index]);
        cmd = DRV_IOW(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_cFlexLookupMode_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, rx_chan_id[index], cmd, &field_val));
        (enable) ? CTC_BIT_SET(sniffing_bitmap[channel_id >> 5], channel_id&0x1F) : CTC_BIT_UNSET(sniffing_bitmap[channel_id >> 5], channel_id&0x1F);
        SetEpeHdrEditSniffingCtl(A, sniffingPacketTxEn_f, &epe_hdr_edit_sniffing_ctl, sniffing_bitmap);
    }
    cmd = DRV_IOW(EpeHdrEditSniffingCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_edit_sniffing_ctl));

    /*set not edit packet on stacking port*/
    field_val = enable ? 1 :0;
    CTC_ERROR_RETURN(sys_usw_port_api_set_internal_property(lchip, gport, SYS_PORT_PROP_VLAN_OPERATION_DIS, field_val));
    field_val = enable ? 0 :1;
    CTC_ERROR_RETURN(sys_usw_port_api_set_internal_property(lchip, gport, SYS_PORT_PROP_UNTAG_DEF_VLAN_EN, field_val));

    ingr_en = CTC_BMP_ISSET(g_stacking_master[lchip]->ing_port_en_bmp, CTC_MAP_GPORT_TO_LPORT(gport));
    egr_en = CTC_BMP_ISSET(g_stacking_master[lchip]->egr_port_en_bmp, CTC_MAP_GPORT_TO_LPORT(gport));
    if (enable)
    {
        /*Encap Output packet Heaer enable*/
        if (ingr_en && egr_en)
        {
            goto end;
        }

        for (index = 0; (0 == ingr_en) && (index < rx_chan_num); index++)
        {
            CTC_ERROR_RETURN(_sys_usw_stacking_encap_header_enable(lchip, rx_chan_id[index], p_encap_hdr?p_encap_hdr:p_trunk->p_encap_hdr, CTC_INGRESS));
        }

        for (index = 0; (0 == egr_en) && (index < tx_chan_num); index++)
        {
            CTC_ERROR_RETURN(_sys_usw_stacking_encap_header_enable(lchip, tx_chan_id[index], p_encap_hdr?p_encap_hdr:p_trunk->p_encap_hdr, CTC_EGRESS));
        }
    }
    else
    {
        if (ingr_en && egr_en)
        {
            goto end;
        }
        for (index = 0; (0 == ingr_en) && (index < rx_chan_num); index++)
        {
            CTC_ERROR_RETURN(_sys_usw_stacking_encap_header_disable( lchip, rx_chan_id[index], CTC_INGRESS));
        }

        for (index = 0; (0 == egr_en) && (index < tx_chan_num); index++)
        {
            CTC_ERROR_RETURN(_sys_usw_stacking_encap_header_disable( lchip, tx_chan_id[index], CTC_EGRESS));
        }
    }

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, (void *)&mac_id));
    if (((DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_C)) || DRV_IS_TMG(lchip)) && (mac_id >= SYS_CPU_MAC_ID_MIN))
    {
        uint8 dp_id = 0;
        uint8 step = 0;
    
        dp_id = (mac_id - SYS_CPU_MAC_ID_MIN) / MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_DP);
        step = (mac_id - SYS_CPU_MAC_ID_MIN) % MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_DP);
        cmd = DRV_IOR(EpeScheduleTruncateCheckCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &epe_sch_trun_cfg) );
        SetEpeScheduleTruncateCheckCfg(V, cfgCpuMac0TruncateCheckEn_f+step, &epe_sch_trun_cfg, (enable?0:1));
        cmd = DRV_IOW(EpeScheduleTruncateCheckCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &epe_sch_trun_cfg));
    }
end:
    if (0 == g_stacking_master[lchip]->binding_trunk)
    {
        field_val = enable ? p_trunk->trunk_id :0;
        cmd = DRV_IOW(DsSrcSgmacGroup_t, DsSrcSgmacGroup_sgmacGroupId_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, tx_chan_id[0], cmd, &field_val));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_change_stacking_port(uint8 lchip, sys_stacking_trunk_info_t* p_sys_trunk,
                                       ctc_stacking_hdr_encap_t* p_encap_hdr, uint32 gport,
                                       uint8 enable )
{
    uint32 chan_id = 0;
    uint16 port_ref_cnt         = 0;
    sys_qos_shape_profile_t shp_profile;
    int32 ret = 0;
    uint32 egr_en = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    sal_memset(&shp_profile,0,sizeof(shp_profile));
    dmps_port_info.gport = gport;

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));

    /*for restore shape profile*/
    _sys_usw_stacking_get_member_ref_cnt(lchip, chan_id, &port_ref_cnt, p_sys_trunk->trunk_id);
    if (port_ref_cnt > 0)
    {
        return CTC_E_NONE;
    }

    egr_en = CTC_BMP_ISSET(g_stacking_master[lchip]->egr_port_en_bmp, CTC_MAP_GPORT_TO_LPORT(gport));
    if (!egr_en)
    {
    if (!DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_RETURN( sys_usw_queue_get_profile_from_hw(lchip, gport, &shp_profile));
    }
    CTC_ERROR_RETURN(sys_usw_queue_set_port_drop_en(lchip, gport, 1, &shp_profile));
    CTC_ERROR_GOTO(_sys_usw_stacking_check_port_status(lchip, gport, &shp_profile), ret, error_proc1);
    }
    CTC_ERROR_GOTO(_sys_usw_stacking_set_stacking_port_en(lchip, p_sys_trunk, p_encap_hdr, gport, enable), ret, error_proc1);

    if (!egr_en)
    {
    CTC_ERROR_GOTO( sys_usw_queue_set_port_drop_en(lchip, gport, 0, &shp_profile), ret, error_proc2);
    }
    
    return CTC_E_NONE;
error_proc2:
    _sys_usw_stacking_set_stacking_port_en(lchip, p_sys_trunk, p_encap_hdr, gport, !enable);
error_proc1:
    if (!egr_en)
    {
    sys_usw_queue_set_port_drop_en(lchip, gport, 0, &shp_profile);
    }
    return ret;

}

STATIC int32
_sys_usw_stacking_create_trunk(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    int32  ret                     = CTC_E_NONE;
    uint32 cmd                     = 0;
    uint8  load_mode                    = 0;
    uint8  trunk_id                 = p_trunk->trunk_id;
    uint16 mem_base                = 0;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    DsLinkAggregateChannelGroup_m  ds_link_aggregate_sgmac_group;

    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL != p_sys_trunk)
    {
        return CTC_E_EXIST;
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_TRUNK, 1);
    p_sys_trunk = (sys_stacking_trunk_info_t*)mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_trunk_info_t));
    if (NULL == p_sys_trunk)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_sys_trunk, 0, sizeof(sys_stacking_trunk_info_t));
    p_sys_trunk->trunk_id = trunk_id;
    p_sys_trunk->flag = p_trunk->flag;
    p_sys_trunk->mode = p_trunk->load_mode;

    if (p_sys_trunk->mode == CTC_STK_LOAD_STATIC_FAILOVER && DRV_FROM_TMM(lchip))
    {
        p_sys_trunk->mode = CTC_STK_LOAD_STATIC;
        CTC_SET_FLAG(p_sys_trunk->flag, CTC_STACKING_TRUNK_LSH);
    }

    /*Alloc member base*/
    CTC_ERROR_GOTO(_sys_usw_stacking_trunk_alloc_mem_base(lchip, p_sys_trunk, p_trunk->max_mem_cnt, &mem_base),
                   ret, Error0);


    if (0 == g_stacking_master[lchip]->mcast_mode)
    {
        CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_add_member(lchip,
                                                                      g_stacking_master[lchip]->p_default_prof_db,
                                                                      p_sys_trunk->trunk_id, 1), ret, Error1);
    }

    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(ds_link_aggregate_sgmac_group));
    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group, mem_base);
    load_mode = (CTC_STK_LOAD_DYNAMIC == p_trunk->load_mode) ? 1 : 0;
    SetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group, load_mode);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggFlowNum_f, &ds_link_aggregate_sgmac_group,
                                           _sys_usw_stacking_dlb_flows2driver(lchip, p_sys_trunk->flow_cnt));
    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group, 0);

    SetDsLinkAggregateChannelGroup(V, lshEn_f, &ds_link_aggregate_sgmac_group, CTC_FLAG_ISSET(p_sys_trunk->flag, CTC_STACKING_TRUNK_LSH)); /*TMM link self healthing, default Enable*/
    SetDsLinkAggregateChannelGroup(V, supportEntropyHashValue_f, &ds_link_aggregate_sgmac_group, 0); /*TMM support entropy, default disable*/

    if (CTC_FLAG_ISSET(p_trunk->flag, CTC_STACKING_TRUNK_LB_HASH_OFFSET_VALID))
    {
        SetDsLinkAggregateChannelGroup(V, hashCfgPriorityIsHigher_f, &ds_link_aggregate_sgmac_group, 1);
        SetDsLinkAggregateChannelGroup(V, hashSelect_f, &ds_link_aggregate_sgmac_group, ((p_trunk->lb_hash_offset / 16)|0x8));
        SetDsLinkAggregateChannelGroup(V, hashOffset_f, &ds_link_aggregate_sgmac_group, p_trunk->lb_hash_offset % 16);
    }

    CTC_ERROR_GOTO(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group), ret, Error2);

    if (p_trunk->encap_hdr.hdr_flag != CTC_STK_HDR_WITH_NONE)
    {
        p_sys_trunk->p_encap_hdr = (ctc_stacking_hdr_encap_t*)mem_malloc(MEM_STK_MODULE, sizeof(ctc_stacking_hdr_encap_t));
        if (NULL == p_sys_trunk->p_encap_hdr)
        {
            ret = CTC_E_NO_MEMORY;
            goto Error2;
        }
        sal_memcpy((uint8*)p_sys_trunk->p_encap_hdr, &p_trunk->encap_hdr, sizeof(ctc_stacking_hdr_encap_t));
    }

    ctc_vector_add(g_stacking_master[lchip]->p_trunk_vec, trunk_id, p_sys_trunk);

    return CTC_E_NONE;

    Error2:
    if (0 == g_stacking_master[lchip]->mcast_mode)
    {
        _sys_usw_stacking_mcast_group_remove_member(lchip, g_stacking_master[lchip]->p_default_prof_db,
                                                          p_sys_trunk->trunk_id, 1);
    }
    Error1:
    _sys_usw_stacking_trunk_free_mem_base(lchip, p_sys_trunk, 0, mem_base);

    Error0:
    mem_free(p_sys_trunk);
    return ret;

}

STATIC int32
_sys_usw_stacking_destroy_trunk(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint32 cmd                     = 0;
    uint8 trunk_id                 = p_trunk->trunk_id;
    uint32 mem_idx                 = 0;
    uint16 gport                   = 0;
    uint16 chan_id                 = 0;
    uint16 mem_base                = 0;
    uint16 mem_cnt                 = 0;
    uint8  gchip_id                = 0;
    uint8  is_dlb                  = 0;
    uint32 port_bitmap[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS]          = {0};

    sys_stacking_trunk_info_t* p_sys_trunk = NULL;

    DsLinkAggregateChannelGroup_m ds_link_aggregate_sgmac_group;
    DsLinkAggregateChannelMember_m ds_link_aggregate_sgmac_member;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
        return CTC_E_NOT_EXIST;

    }
    sys_usw_get_gchip_id(lchip, &gchip_id);
    /*cancel ucast path*/
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_TRUNK, 1);

    CTC_ERROR_RETURN(_sys_usw_stacking_get_trunk_info(lchip, trunk_id, &mem_cnt, &mem_base, &is_dlb));

    if (!is_dlb)
    {
        for (mem_idx = 0; mem_idx < mem_cnt; mem_idx++)
        {
            cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, mem_idx + mem_base, cmd, &ds_link_aggregate_sgmac_member));
            chan_id = GetDsLinkAggregateChannelMember(V, channelId_f, &ds_link_aggregate_sgmac_member);
            gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, SYS_USW_CHANNEL_DECODE(chan_id)));

            _sys_usw_stacking_change_stacking_port(lchip,p_sys_trunk, NULL, gport,FALSE);
            SetDsLinkAggregateChannelMember(V, channelId_f, &ds_link_aggregate_sgmac_member, MCHIP_CAP(SYS_CAP_CHANID_DROP));
            cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, mem_idx + mem_base, cmd, &ds_link_aggregate_sgmac_member));
        }
    }
    else
    {
        DsLinkAggregateChannelMemberSet_m mem_set;
        uint8 step = 0;

        step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

        cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &mem_set));

        for (mem_idx = 0; mem_idx < mem_cnt; mem_idx++)
        {
            if (GetDsLinkAggregateChannelMemberSet(V, array_0_valid_f + mem_idx*step, &mem_set))
            {
                chan_id = GetDsLinkAggregateChannelMemberSet(V, array_0_channelId_f + mem_idx*step, &mem_set);
                gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, SYS_USW_CHANNEL_DECODE(chan_id)));
                _sys_usw_stacking_change_stacking_port(lchip,p_sys_trunk, NULL, gport,FALSE);
        
                SetDsLinkAggregateChannelMemberSet(V, array_0_channelId_f + mem_idx*step, &mem_set, MCHIP_CAP(SYS_CAP_CHANID_DROP));
                SetDsLinkAggregateChannelMemberSet(V, array_0_sliceId_f + mem_idx*step, &mem_set, 0);
                SetDsLinkAggregateChannelMemberSet(V, array_0_valid_f + mem_idx*step, &mem_set, 0);
            }
        }
        cmd = DRV_IOW(DsLinkAggregateChannelMemberSet_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &mem_set));
    }

    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(DsLinkAggregateChannelGroup_m));
    sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(DsLinkAggregateChannelMember_m));

    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group, mem_base);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group, 0);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group, 0);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggFlowNum_f, &ds_link_aggregate_sgmac_group, 0);
    DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group);

    cmd = DRV_IOW(DsMetNonUcCflexMemberBitmap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, port_bitmap));
    if (DRV_FROM_AT(lchip))
    {
        cmd = DRV_IOW(DsMetExcpCflexMemberBitmap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, port_bitmap));
    }

    if (0 == g_stacking_master[lchip]->mcast_mode)
    {
        _sys_usw_stacking_mcast_group_remove_member(lchip,
                                                          g_stacking_master[lchip]->p_default_prof_db,
                                                          p_sys_trunk->trunk_id, 1);
    }

    if ((1 == g_stacking_master[lchip]->bind_mcast_en)
    && (0 == _sys_usw_stacking_is_trunk_have_member(lchip)))
    {
        _sys_usw_stacking_all_mcast_bind_en(lchip, 0);
    }

    _sys_usw_stacking_remove_trunk_path(lchip, p_sys_trunk->trunk_id);
    /*Free trunk mem base*/
    _sys_usw_stacking_trunk_free_mem_base(lchip, p_sys_trunk,
                                            0, mem_base);

    if (p_sys_trunk->p_encap_hdr)
    {
        mem_free(p_sys_trunk->p_encap_hdr);
    }

    ctc_vector_del(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    mem_free(p_sys_trunk);
    return CTC_E_NONE;
}

STATIC bool
_sys_usw_stacking_find_trunk_port(uint8 lchip, uint8 trunk_id, uint16 chan_id, uint32* index)
{
    uint32 mem_index               = 0;
    uint16 mem_base                = 0;
    uint16 mem_cnt                 = 0;
    uint32 cmd                     = 0;
    uint32 tmp_chan_id             = 0;
    DsLinkAggregateChannelMember_m ds_link_aggregate_sgmac_member;
    uint8  is_dlb                  = 0;

    CTC_PTR_VALID_CHECK(index);

    CTC_ERROR_RETURN(_sys_usw_stacking_get_trunk_info(lchip, trunk_id, &mem_cnt, &mem_base, &is_dlb));

    sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(DsLinkAggregateChannelMember_m));

    if (!is_dlb)
    {
        cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
        for (mem_index = 0; mem_index < mem_cnt; mem_index++)
        {
             CTC_ERROR_RETURN(DRV_IOCTL(lchip, mem_index + mem_base, cmd, &ds_link_aggregate_sgmac_member));
            tmp_chan_id = GetDsLinkAggregateChannelMember(V, channelId_f, &ds_link_aggregate_sgmac_member);
            if (SYS_USW_CHANNEL_DECODE(tmp_chan_id) == chan_id)
            {
                *index = mem_index;
                return TRUE;
            }
        }
    }
    else
    {
        uint16 step = 0;
        step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

        for (mem_index = 0; mem_index < mem_cnt; mem_index++)
        {
            cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DsLinkAggregateChannelMemberSet_array_0_channelId_f + mem_index*step);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, trunk_id, cmd, &tmp_chan_id));
            if (SYS_USW_CHANNEL_DECODE(tmp_chan_id) == chan_id)
            {
                *index = mem_index;
                return TRUE;
            }
        }
    }

    return FALSE;
}

STATIC int32
_sys_usw_stacking_update_non_uc_port(uint8 lchip, uint8 trunk_id, uint32* add_ports, uint16 add_num, uint16 port, uint8 is_add)
{
    uint32 cmd = 0;
    uint16 hash = 0;
    uint16 port_i = 0;
    uint16 max_hash = 0;
    uint16 mem_idx = 0;
    uint16 port_cnt = 0;
    uint32 port_bitmap[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    uint32 block_bitmap[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    uint32 port_array[SYS_STK_MAX_PORT_CNT] = {0};
    uint32 trunk_hash_base = 0;
    uint16 mem_port = 0;
    uint32* p_dma_mem = NULL;
    uint32 tbl_addr = 0;
    sys_dma_tbl_rw_t dma_cfg;
    DsMetNonUcLagBlockMask_m  block_mask;
    uint32 port_bitmap_old[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    uint8 tmp_port_cnt = 0;

    sal_memset(&dma_cfg, 0, sizeof(dma_cfg));
    cmd = DRV_IOR(DsMetNonUcCflexMemberBitmap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, port_bitmap));
    sal_memcpy(port_bitmap_old, port_bitmap, sizeof(port_bitmap_old));

    if (is_add)
    {
        CTC_BIT_SET(port_bitmap[port / 32], port % 32);
    }
    else
    {
        CTC_BIT_UNSET(port_bitmap[port / 32], port % 32);
    }

    CTC_ERROR_RETURN(_sys_usw_stacking_get_member_ports(lchip, trunk_id, &port_array[0],&tmp_port_cnt));
    port_cnt = tmp_port_cnt;
    
    if (NULL != add_ports)
    {
        sal_memcpy((uint8*)(&port_array[tmp_port_cnt]), (uint8*)add_ports, add_num*sizeof(uint32));
        port_cnt = port_cnt+add_num;
    }

    switch(g_stacking_master[lchip]->trunk_mode)
    {
        case CTC_STACKING_TRUNK_MODE_0:
        case CTC_STACKING_TRUNK_MODE_2:
            trunk_hash_base = trunk_id<<4;/*64 group, per group up to 16 member*/
            max_hash = 1<<4;
            break;
        case CTC_STACKING_TRUNK_MODE_1:
            trunk_hash_base = trunk_id<<5;/*32 group, per group up to 32 member*/
            max_hash = 1<<5;
            break;
        case CTC_STACKING_TRUNK_MODE_3:
            trunk_hash_base = 0;
            max_hash = 1<<8;
            break;
        case CTC_STACKING_TRUNK_MODE_4:
            trunk_hash_base = trunk_id<<3;/*128 group, per group up to 8 member*/
            max_hash = 1<<3;
            break;
        case CTC_STACKING_TRUNK_MODE_5:
            trunk_hash_base = trunk_id<<6;/*16 group, per group up to 64 member*/
            max_hash = 1<<6;
            break;
        case CTC_STACKING_TRUNK_MODE_6:
            trunk_hash_base = trunk_id<<7;/*8 group, per group up to 128 member*/
            max_hash = 1<<7;
            break;
        default:
            return CTC_E_INVALID_PARAM;
            break;
    }

    drv_usw_table_get_hw_addr(lchip, DsMetNonUcLagBlockMask_t, (trunk_hash_base), &tbl_addr, FALSE);
    sys_usw_dma_get_dma_memory(lchip, 0, &p_dma_mem);
    if (p_dma_mem)
    {
        /*1.clear local block mask*/
        for (hash = 0; hash < max_hash; hash++)
        {
            uint32* p_dma_mem_tmp = NULL;
            p_dma_mem_tmp = (uint32*)((uint8 *)p_dma_mem + TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t)*((trunk_hash_base) + hash));
            GetDsMetNonUcLagBlockMask(A, blockPbmMask_f, p_dma_mem_tmp, &block_bitmap);
            /*Need mask new add/remove Port to avoid bitmap unset and mask set cause non-uc packet drop*/            
            if (((~block_bitmap[port / 32] & port_bitmap_old[port / 32]) == (1<<(port % 32))) && port_cnt)
            {                
                mem_idx = hash % port_cnt; 
                mem_port = CTC_MAP_GPORT_TO_LPORT(port_array[mem_idx]);
                CTC_BIT_UNSET(block_bitmap[mem_port / 32], mem_port % 32);
            }            
            CTC_BMP_SET(block_bitmap, port);
            
            SetDsMetNonUcLagBlockMask(A, blockPbmMask_f, p_dma_mem_tmp, &block_bitmap);
#if (SDB_DISABLE != SDB_MODE)
            drv_sdb_store(lchip, DsMetNonUcLagBlockMask_t, ((trunk_hash_base) + hash), p_dma_mem_tmp, TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t), 0);
#endif
        }

        /*2.write all  block entry  by DMA: DsMetNonUcLagBlockMask  */
        p_dma_mem = (uint32*)((uint8 *)p_dma_mem + TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t)*(trunk_hash_base));
        dma_cfg.tbl_addr = tbl_addr;
        dma_cfg.buffer = p_dma_mem;
        dma_cfg.entry_num = max_hash;
        dma_cfg.entry_len = TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t);
        dma_cfg.user_dma_mode = 1;
        dma_cfg.entry_offset = TABLE_ENTRY_OFFSET(lchip, DsMetNonUcLagBlockMask_t);
        CTC_ERROR_RETURN(MCHIP_DMA(lchip)->dma_write_table(lchip, &dma_cfg));
    }
    else
    {
        for (hash = 0; hash < max_hash; hash++)
        {
            cmd = DRV_IOR(DsMetNonUcLagBlockMask_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, (trunk_hash_base) + hash, cmd, &block_mask));
            GetDsMetNonUcLagBlockMask(A, blockPbmMask_f, &block_mask, &block_bitmap);
            /*Need mask new add Port to avoid bitmap unset and mask set cause non-uc packet drop*/
            CTC_BMP_SET(block_bitmap, port);
            if (((~block_bitmap[port / 32] & port_bitmap_old[port / 32]) == (1<<(port % 32))) && port_cnt)
            {
                mem_idx = hash % port_cnt; 
                mem_port = CTC_MAP_GPORT_TO_LPORT(port_array[mem_idx]);
                CTC_BIT_UNSET(block_bitmap[mem_port / 32], mem_port % 32);
            }
            SetDsMetNonUcLagBlockMask(A, blockPbmMask_f, &block_mask, &block_bitmap);
            cmd = DRV_IOW(DsMetNonUcLagBlockMask_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, (trunk_hash_base) + hash, cmd, &block_mask));
        }
    }

    /*write bitmap before mask, to avoid add trunk member cause non-uc packet drop*/
    cmd = DRV_IOW(DsMetNonUcCflexMemberBitmap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, port_bitmap));
    if (DRV_FROM_AT(lchip))
    {
        cmd = DRV_IOW(DsMetExcpCflexMemberBitmap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, port_bitmap));
    }

    /*3.set block mask*/
    sys_usw_dma_get_dma_memory(lchip, 0, &p_dma_mem);
    if (p_dma_mem)
    {
        for(hash = 0; hash < max_hash ;hash++)
        {
            uint32* p_dma_mem_tmp = NULL;

            p_dma_mem_tmp = (uint32*)((uint8 *)p_dma_mem + TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t)*((trunk_hash_base) + hash));
            for (port_i = 0; port_i < SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS; port_i++)
            {
                *((uint32*)((uint32*)p_dma_mem_tmp + port_i)) &= ~port_bitmap_old[port_i];
                *((uint32*)((uint32*)p_dma_mem_tmp + port_i)) |= port_bitmap[port_i];
            }
            GetDsMetNonUcLagBlockMask(A, blockPbmMask_f, p_dma_mem_tmp, &block_bitmap);
            for(port_i = 0; port_i < port_cnt; port_i++)
            {                
                mem_idx = hash % port_cnt;
                mem_port = CTC_MAP_GPORT_TO_LPORT(port_array[port_i]);
                if (port_i == mem_idx)
                {    /*port pass*/
                    CTC_BIT_UNSET(block_bitmap[mem_port / 32], mem_port % 32);
                }
                else
                {
                    CTC_BIT_SET(block_bitmap[mem_port / 32], mem_port % 32);
                }
            }
            SetDsMetNonUcLagBlockMask(A, blockPbmMask_f, p_dma_mem_tmp, &block_bitmap);
#if (SDB_DISABLE != SDB_MODE)
            drv_sdb_store(lchip, DsMetNonUcLagBlockMask_t, ((trunk_hash_base) + hash), p_dma_mem_tmp, TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t), 0);
#endif
        }

        p_dma_mem = (uint32*)((uint8 *)p_dma_mem + TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t)*(trunk_hash_base));
        dma_cfg.tbl_addr = tbl_addr;
        dma_cfg.buffer = p_dma_mem;
        dma_cfg.entry_num = max_hash;
        dma_cfg.entry_len = TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t);
        dma_cfg.user_dma_mode = 1;
        dma_cfg.entry_offset = TABLE_ENTRY_OFFSET(lchip, DsMetNonUcLagBlockMask_t);
        CTC_ERROR_RETURN(MCHIP_DMA(lchip)->dma_write_table(lchip, &dma_cfg));
    }
    else
    {
        for(hash = 0; hash < max_hash ;hash++)
        {
            cmd = DRV_IOR(DsMetNonUcLagBlockMask_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, (trunk_hash_base) + hash, cmd, &block_mask))

            for (port_i = 0; port_i < SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS; port_i++)
            {
                *((uint32*)&block_mask+port_i) &= ~port_bitmap_old[port_i];
                *((uint32*)&block_mask+port_i) |= port_bitmap[port_i];
            }

            for(port_i = 0; port_i < port_cnt; port_i++)
            {                
                mem_idx = hash % port_cnt;
                mem_port = CTC_MAP_GPORT_TO_LPORT(port_array[port_i]);
                GetDsMetNonUcLagBlockMask(A, blockPbmMask_f, &block_mask, &block_bitmap);
                if (port_i == mem_idx)
                {    /*port pass*/
                    CTC_BIT_UNSET(block_bitmap[mem_port / 32], mem_port % 32);
                }
                else
                {
                    CTC_BIT_SET(block_bitmap[mem_port / 32], mem_port % 32);
                }

                SetDsMetNonUcLagBlockMask(A, blockPbmMask_f, &block_mask, &block_bitmap);
            }

            cmd = DRV_IOW(DsMetNonUcLagBlockMask_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip,(trunk_hash_base) + hash  , cmd, &block_mask))

        }
    }

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_stacking_update_self_healing(uint8 lchip, uint8 trunk_id)
{
    uint32 cmd = 0;
    uint8 gchip = 0;
    uint32 chan_id = 0;
    uint32 chan_bak_id = 0;
    uint8 port_cnt = 0;
    int8 step = 0;
    int8 step2 = 0;
    int8 step3 = 0;
    uint16 port_i = 0;
    uint16 port_j = 0;
    uint16 backup_cnt = 0;
    uint32 port_bitmap[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    uint16 port_array[SYS_STK_MAX_PORT_CNT] = {0};
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    CflexLagLinkSelfHealingSet_m uc_set;
    DsMetPortLagLinkSelfHealingSet_m mc_set;
    DsMetExcpPortLagLinkSelfHealingSet_m excepton_set;

    cmd = DRV_IOR(DsMetNonUcCflexMemberBitmap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, port_bitmap));

    CTC_BMP_ITER_BEGIN(port_bitmap, port_i)
    {
        port_array[port_cnt] = port_i;
        port_cnt++;
    }
    CTC_BMP_ITER_END(port_bitmap, port_i);

    step = DsMetPortLagLinkSelfHealingSet_gMember_1_destId_f - DsMetPortLagLinkSelfHealingSet_gMember_0_destId_f;
    step2 = CflexLagLinkSelfHealingSet_gMember_1_channelId_f - CflexLagLinkSelfHealingSet_gMember_0_channelId_f;
    step3 = DsMetExcpPortLagLinkSelfHealingSet_gMember_1_destChannelId_f - DsMetExcpPortLagLinkSelfHealingSet_gMember_0_destChannelId_f;

    sys_usw_get_gchip_id(lchip, &gchip);

    for (port_i = 0; port_i < port_cnt; port_i++)
    {
        dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, port_array[port_i]);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info,
                                                            SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
        if (!SYS_IS_NETWORK_CHANNEL(chan_id))
        {
            continue;
        }
        cmd = DRV_IOR(CflexLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &uc_set));

        cmd = DRV_IOR(DsMetPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, port_array[port_i], cmd, &mc_set));

        if (DRV_FROM_AT(lchip))
        {
            cmd = DRV_IOR(DsMetExcpPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, port_array[port_i], cmd, &excepton_set));
        }
        backup_cnt = 0;

        for (port_j = 0; port_j < port_cnt; port_j++)
        {
            if (port_i == port_j)
            {
                continue;
            }

            dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, port_array[port_j]);
            CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info,
                                                            SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_bak_id));
            if (!SYS_IS_NETWORK_CHANNEL(chan_bak_id))
            {
                continue;
            }

            SetCflexLagLinkSelfHealingSet(V, gMember_0_sliceId_f + backup_cnt*step2, &uc_set, 0);
            SetCflexLagLinkSelfHealingSet(V, gMember_0_channelId_f + backup_cnt*step2, &uc_set, chan_bak_id);

            SetDsMetPortLagLinkSelfHealingSet(V, gMember_0_destChipId_f + backup_cnt*step, &mc_set, gchip);
            SetDsMetPortLagLinkSelfHealingSet(V, gMember_0_destId_f + backup_cnt*step, &mc_set, port_array[port_j]);
            SetDsMetPortLagLinkSelfHealingSet(V, gMember_0_destChannelId_f + backup_cnt*step, &mc_set, chan_bak_id);
            if (DRV_FROM_AT(lchip))
            {
                SetDsMetExcpPortLagLinkSelfHealingSet(V, gMember_0_destChannelId_f + backup_cnt*step3, &mc_set, gchip);
                SetDsMetExcpPortLagLinkSelfHealingSet(V, gMember_0_destChipId_f + backup_cnt*step3, &mc_set, port_array[port_j]);
                SetDsMetExcpPortLagLinkSelfHealingSet(V, gMember_0_destChannelId_f + backup_cnt*step3, &mc_set, chan_bak_id);
            }
            backup_cnt++;
            if (backup_cnt >= 8)
            {
                break;
            }
        }

        if (backup_cnt)
        {
            SetCflexLagLinkSelfHealingSet(V, setSize_f, &uc_set, backup_cnt - 1);

            SetDsMetPortLagLinkSelfHealingSet(V, setSize_f, &mc_set, backup_cnt - 1);
            SetDsMetPortLagLinkSelfHealingSet(V, channelId_f, &mc_set, chan_id);
            SetDsMetPortLagLinkSelfHealingSet(V, nonUcastToLagLinkSelfHealingEn_f, &mc_set, 1);
            SetDsMetPortLagLinkSelfHealingSet(V, logToLagLinkSelfHealingEn_f, &mc_set, 1);

            if (DRV_FROM_AT(lchip))
            {
                SetDsMetExcpPortLagLinkSelfHealingSet(V, setSize_f, &excepton_set, backup_cnt - 1);
                SetDsMetExcpPortLagLinkSelfHealingSet(V, channelId_f, &excepton_set, chan_id);
                SetDsMetExcpPortLagLinkSelfHealingSet(V, logToLagLinkSelfHealingEn_f, &excepton_set, 1);
            }
        }
        else
        {
            sal_memset(&uc_set, 0, sizeof(uc_set));
            SetCflexLagLinkSelfHealingSet(V, gMember_0_channelId_f, &uc_set, MCHIP_CAP(SYS_CAP_CHANID_DROP));

            SetDsMetPortLagLinkSelfHealingSet(V, nonUcastToLagLinkSelfHealingEn_f, &mc_set, 0);
            SetDsMetPortLagLinkSelfHealingSet(V, logToLagLinkSelfHealingEn_f, &mc_set, 0);

            if (DRV_FROM_AT(lchip))
            {
                SetDsMetExcpPortLagLinkSelfHealingSet(V, logToLagLinkSelfHealingEn_f, &excepton_set, 0);
            }
        }

        cmd = DRV_IOW(CflexLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &uc_set));

        cmd = DRV_IOW(DsMetPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, port_array[port_i], cmd, &mc_set));

        if (DRV_FROM_AT(lchip))
        {
            cmd = DRV_IOW(DsMetExcpPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, port_array[port_i], cmd, &excepton_set));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_add_trunk_port(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint16 mem_cnt                 = 0;
    uint16 mem_base                = 0;
    uint32 cmd                     = 0;
    uint8 trunk_id                 = p_trunk->trunk_id;
    uint32 gport                   = p_trunk->gport;
    uint32 index                   = 0;
    uint32 chan_id                 = 0;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsLinkAggregateChannelGroup_m ds_link_aggregate_sgmac_group;
    DsLinkAggregateChannelMember_m ds_link_aggregate_sgmac_member;
    int32 ret = 0;
    uint8  is_dlb                  = 0;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (SYS_DMPS_INVALID_CHAN_ID == chan_id)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid localphy port \n");
        return CTC_E_INVALID_PORT;
    }

    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
        return CTC_E_NOT_EXIST;
    }
    if(p_sys_trunk->replace_en)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Only support replace API operation \n");
        return CTC_E_PARAM_CONFLICT;
    }

    if (TRUE == _sys_usw_stacking_find_trunk_port(lchip, trunk_id, chan_id, &index))
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk member port exist\n");
        return CTC_E_EXIST;
    }

    SYS_STK_DBG_INFO("Add uplink gport :%d, chan_id:%d\n", gport, chan_id);

    CTC_ERROR_RETURN(_sys_usw_stacking_get_trunk_info(lchip, trunk_id, &mem_cnt, &mem_base, &is_dlb));

    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(DsLinkAggregateChannelGroup_m));
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group));

    if (((MCHIP_CAP(SYS_CAP_STK_TRUNK_DLB_MAX_MEMBERS) == mem_cnt) && (CTC_STK_LOAD_DYNAMIC == p_sys_trunk->mode))
        || ((p_sys_trunk->max_mem_cnt == mem_cnt) && (CTC_STK_LOAD_DYNAMIC != p_sys_trunk->mode)))
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk exceed max member port\n");
        return CTC_E_INVALID_CONFIG;
    }
   /*for restore shape profile*/
    if (p_trunk->encap_hdr.hdr_flag != CTC_STK_HDR_WITH_NONE)
    {
        CTC_ERROR_RETURN(_sys_usw_stacking_change_stacking_port(lchip,p_sys_trunk, &(p_trunk->encap_hdr), gport,TRUE));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_usw_stacking_change_stacking_port(lchip,p_sys_trunk, NULL, gport,TRUE));
    }

    if (p_sys_trunk->mode == CTC_STK_LOAD_DYNAMIC)
    {
        CTC_ERROR_GOTO(_sys_usw_stacking_dlb_add_member(lchip, trunk_id, mem_cnt, chan_id), ret, end);
    }
    else if (CTC_STK_LOAD_STATIC_FAILOVER == p_sys_trunk->mode)
    {
        CTC_ERROR_GOTO(_sys_usw_stacking_failover_add_member(lchip, trunk_id, gport), ret, end);
    }

    if(CTC_FLAG_ISSET(p_sys_trunk->flag, CTC_STACKING_TRUNK_MEM_ASCEND_ORDER))
    {
        uint8 temp_mem_idx = mem_cnt;
        DsLinkAggregateChannelMember_m  hw_member;
        uint32 cmdr = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
        uint32 cmdw = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);

        for(; temp_mem_idx > 0; temp_mem_idx--)
        {
            DRV_IOCTL(lchip, temp_mem_idx+mem_base-1, cmdr, &hw_member);
            if(SYS_USW_CHANNEL_ENCODE(chan_id) >= GetDsLinkAggregateChannelMember(V, channelId_f, &hw_member))
            {
                break;
            }
            DRV_IOCTL(lchip, temp_mem_idx+mem_base, cmdw, &hw_member);
        }

        index = temp_mem_idx;
    }
    else
    {
        index = mem_cnt;
    }

    if (!is_dlb)
    {
        sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(ds_link_aggregate_sgmac_member));
        cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
        SetDsLinkAggregateChannelMember(V, channelId_f, &ds_link_aggregate_sgmac_member, SYS_USW_CHANNEL_ENCODE(chan_id));
        SetDsLinkAggregateChannelMember(V, sliceId_f, &ds_link_aggregate_sgmac_member, 0); /*TODO, multi-slices!!!!!*/

        DRV_IOCTL(lchip, mem_base+index, cmd, &ds_link_aggregate_sgmac_member);
    }

    /*update trunk members*/
    mem_cnt++;

    if ((0 == g_stacking_master[lchip]->bind_mcast_en))
    {
        _sys_usw_stacking_all_mcast_bind_en(lchip, 1);
    }

    /*for the first member in dlb mode ,need flush active */
    if ((CTC_STK_LOAD_DYNAMIC == p_sys_trunk->mode) && (1 == mem_cnt))
    {
       _sys_usw_stacking_clear_flow_active(lchip, trunk_id);
    }
    if(mem_cnt==MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS)&&DRV_IS_TMG(lchip))
    {
        mem_cnt = 0;
    }
    SetDsLinkAggregateChannelGroup(V, grpNotEmpty_f, &ds_link_aggregate_sgmac_group, 1);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group, mem_cnt);

    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group);

    /*set non-uc ports*/
    if (DRV_FROM_TMM(lchip))
    {
        /*linkagg and stacking share same table*/
        MCHIP_LAG_BLOCK_LOCK(lchip);
        _sys_usw_stacking_update_non_uc_port(lchip, trunk_id, NULL, 0, CTC_MAP_GPORT_TO_LPORT(gport), 1);
        MCHIP_LAG_BLOCK_UNLOCK(lchip);

        if (CTC_FLAG_ISSET(p_sys_trunk->flag, CTC_STACKING_TRUNK_LSH))
        {
            _sys_usw_stacking_update_self_healing(lchip, trunk_id);
        }
    }

    return CTC_E_NONE;

end:
   _sys_usw_stacking_change_stacking_port(lchip,p_sys_trunk, NULL, gport,FALSE);
    return ret;
}

STATIC int32
_sys_usw_stacking_remove_trunk_port(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint32 cmd                     = 0;
    uint8 trunk_id                 = 0;
    uint32 gport                   = p_trunk->gport;
    uint16 last_lport              = 0;
    uint32 mem_index               = 0;
    uint32 index                   = 0;
    uint32 field_val               = 0;
    uint32 chan_id                 = 0;
    uint16 chan_tmp                = 0;
    uint16 mem_cnt                 = 0;
    uint16 mem_base                = 0;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsLinkAggregateChannelMember_m ds_link_aggregate_sgmac_member;
    uint8  is_dlb                  = 0;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    trunk_id = p_trunk->trunk_id;
    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (SYS_DMPS_INVALID_CHAN_ID == chan_id)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid localphy port \n");
		return CTC_E_INVALID_PORT;
    }

    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
		return CTC_E_NOT_EXIST;
    }

    if(p_sys_trunk->replace_en)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Only support replace API operation \n");
        return CTC_E_PARAM_CONFLICT;
    }
    if (FALSE == _sys_usw_stacking_find_trunk_port(lchip, trunk_id, chan_id, &mem_index))
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk member port not exist\n");
			return CTC_E_NOT_EXIST;
    }

    SYS_STK_DBG_INFO("Remove gport %d, mem_index = %d\n", gport, mem_index);

    CTC_ERROR_RETURN(_sys_usw_stacking_get_trunk_info(lchip, trunk_id, &mem_cnt, &mem_base, &is_dlb));

    if ((mem_index < (mem_cnt - 1)) && (p_sys_trunk->mode != CTC_STK_LOAD_DYNAMIC))
    {   /*Need replace this member using last member*/
        sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(ds_link_aggregate_sgmac_member));
        if (CTC_FLAG_ISSET(p_sys_trunk->flag, CTC_STACKING_TRUNK_MEM_ASCEND_ORDER))
        {
            uint8 tmp_index = mem_index;
            DsLinkAggregateChannelMember_m  hw_member;
            uint32 cmdr = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            uint32 cmdw = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);

            for(;tmp_index < mem_cnt-1; tmp_index++)
            {
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, tmp_index+mem_base+1, cmdr, &hw_member));
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, tmp_index+mem_base, cmdw, &hw_member));
            }
        }
        else
        {
            index = mem_base + mem_cnt - 1;
            cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_link_aggregate_sgmac_member));
            chan_tmp = GetDsLinkAggregateChannelMember(V, channelId_f, &ds_link_aggregate_sgmac_member);
            if (0xFF == chan_tmp)
            {
                SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid localphy port \n");
                return CTC_E_INVALID_PORT;

            }

            sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(ds_link_aggregate_sgmac_member));
            SetDsLinkAggregateChannelMember(V, channelId_f, &ds_link_aggregate_sgmac_member, chan_tmp);
            SetDsLinkAggregateChannelMember(V, sliceId_f, &ds_link_aggregate_sgmac_member, 0); /*TODO, multi-slices!!!!!*/

            SYS_STK_DBG_INFO("Need replace this member using last member drv lport:%d, chan:%d\n", last_lport, chan_tmp);

            index = mem_base + mem_index;
            cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_link_aggregate_sgmac_member));
        }
    }

    /*update trunk members*/
    mem_cnt--;
    field_val = mem_cnt;
    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DsLinkAggregateChannelGroup_channelLinkAggMemNum_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, trunk_id, cmd, &field_val));

    if (p_sys_trunk->mode == CTC_STK_LOAD_DYNAMIC)
    {
        _sys_usw_stacking_dlb_del_member(lchip, trunk_id, mem_index, mem_cnt, chan_id);
    }
    else if (CTC_STK_LOAD_STATIC_FAILOVER == p_sys_trunk->mode)
    {
        _sys_usw_stacking_failover_del_member(lchip, trunk_id, gport);
    }

    if ((1 == g_stacking_master[lchip]->bind_mcast_en)
        && (0 == _sys_usw_stacking_is_trunk_have_member(lchip)))
    {
        _sys_usw_stacking_all_mcast_bind_en(lchip, 0);
    }

    /*set non-uc ports*/
    if (DRV_FROM_TMM(lchip))
    {
        /*linkagg and stacking share same table*/
        MCHIP_LAG_BLOCK_LOCK(lchip);
        _sys_usw_stacking_update_non_uc_port(lchip, trunk_id, NULL, 0, CTC_MAP_GPORT_TO_LPORT(gport), 0);
        MCHIP_LAG_BLOCK_UNLOCK(lchip);

        if (CTC_FLAG_ISSET(p_sys_trunk->flag, CTC_STACKING_TRUNK_LSH))
        {
            _sys_usw_stacking_update_self_healing(lchip, trunk_id);
        }
    }

    /*for restore shape profile*/
    CTC_ERROR_RETURN(_sys_usw_stacking_change_stacking_port(lchip,p_sys_trunk, NULL, gport,FALSE));
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_find_no_dupicated(uint8 lchip, uint32* new_members, uint8 new_cnt,
                                          uint32* old_members, uint8 old_cnt,
                                          uint32* find_members, uint8* find_cnt)
{
    uint16 count = 0;
    uint16 loop, loop1;
    uint8  is_new_member;
    uint8  duplicated_member;
    uint32  temp_port;
    uint32 chan_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    for(loop=0;loop<new_cnt; loop++)
    {
        dmps_port_info.gport = new_members[loop];
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
        if (SYS_DMPS_INVALID_CHAN_ID == chan_id)
        {
           return CTC_E_INVALID_LOCAL_PORT;
        }
        temp_port = new_members[loop];
        is_new_member = 1;
        for(loop1=0; loop1 < old_cnt; loop1++)
        {
            if(temp_port == old_members[loop1])
            {
                is_new_member = 0;
                break;
            }
        }
        if(is_new_member)
        {
            duplicated_member = 0;
            for(loop1=0; loop1 < count;loop1++)
            {
                if(temp_port == find_members[loop1])
                {
                    duplicated_member = 1;
                    break;
                }
            }

            if(!duplicated_member)
            {
                find_members[count++] = temp_port;
            }
        }
    }
    *find_cnt = count;
    return CTC_E_NONE;
}

int32
_sys_usw_stacking_get_member_ports(uint8 lchip, uint8 trunk_id, uint32* p_gports, uint8* cnt)
{
	uint32 field_val = 0;
	uint16 mem_cnt = 0;
	uint16 mem_base = 0;
	uint32 cmd = 0;
	uint16 mem_idx = 0;
    uint8 gchip_id = 0;
    DsLinkAggregateChannelGroup_m ds_link_aggregate_sgmac_group;
    DsLinkAggregateChannelMember_m ds_link_aggregate_sgmac_member;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sys_usw_get_gchip_id(lchip, &gchip_id);

    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(DsLinkAggregateChannelGroup_m));
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group));

	mem_cnt = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group);
	mem_base    = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group);

    sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(ds_link_aggregate_sgmac_member));

    if (GetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group) != 1)
    {
        cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
        for (mem_idx = 0; mem_idx < mem_cnt; mem_idx++)
        {
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mem_base + mem_idx, cmd, &field_val));
            p_gports[mem_idx] =  CTC_MAP_LPORT_TO_GPORT(gchip_id, SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, SYS_USW_CHANNEL_DECODE(field_val)));
        }
    }
    else
    {
        uint16 step = 0;
        step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

        for (mem_idx = 0; mem_idx < mem_cnt; mem_idx++)
        {
            cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DsLinkAggregateChannelMemberSet_array_0_channelId_f + mem_idx*step);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, trunk_id, cmd, &field_val));
            p_gports[mem_idx] = CTC_MAP_LPORT_TO_GPORT(gchip_id, SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, SYS_USW_CHANNEL_DECODE(field_val)));
        }
    }
    *cnt = mem_cnt;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_replace_trunk_ports(uint8 lchip, uint8 trunk_id, uint32* gports, uint8 mem_ports)
{
    int32  ret = 0;
    uint32 cmd;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    sys_stacking_trunk_info_t  bk_trunk;
    uint32 fld_val = 0;
    uint8  loop = 0;
    uint8  add_loop = 0;
    uint8  del_loop = 0;
    uint16 mem_base = 0;
    uint8  add_ports_num;
    uint8  del_ports_num;
    uint32 add_ports[SYS_STK_MAX_PORT_CNT] = {0};
    uint32 del_ports[SYS_STK_MAX_PORT_CNT] = {0};
    uint32 old_ports[SYS_STK_MAX_PORT_CNT] = {0};
    uint8  old_ports_num;
    uint32 chan_id = 0;
    uint8  bk_replace_en = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsLinkAggregateChannelGroup_m agg_group;

    SYS_STK_DBG_FUNC();
    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        return CTC_E_STK_TRUNK_NOT_EXIST;
    }

    if (CTC_STK_LOAD_STATIC != p_sys_trunk->mode)
    {
        return CTC_E_NOT_SUPPORT;
    }

    sal_memcpy(&bk_trunk, p_sys_trunk, sizeof(sys_stacking_trunk_info_t));
    _sys_usw_stacking_get_member_ports(lchip, trunk_id, &old_ports[0],&old_ports_num);

    if (mem_ports > p_sys_trunk->max_mem_cnt)
    {
        return CTC_E_STK_TRUNK_EXCEED_MAX_MEMBER_PORT;
    }

    /*1.find add ports */
    /*2.find delete ports */
    CTC_ERROR_GOTO(_sys_usw_stacking_find_no_dupicated(lchip, gports, mem_ports, old_ports, old_ports_num, add_ports, &add_ports_num), ret, error_proc);
    CTC_ERROR_GOTO(_sys_usw_stacking_find_no_dupicated(lchip, old_ports, old_ports_num, gports, mem_ports, del_ports, &del_ports_num), ret, error_proc);

    /*3. set add ports, change normal port to stacking port */
    for (add_loop = 0; add_loop < add_ports_num; add_loop++)
    {
        CTC_ERROR_GOTO(_sys_usw_stacking_change_stacking_port(lchip, p_sys_trunk, NULL, add_ports[add_loop], TRUE), ret, error_proc);

        /*set non-uc ports*/
        if (DRV_FROM_TMM(lchip))
        {
            /*linkagg and stacking share same table*/
            MCHIP_LAG_BLOCK_LOCK(lchip);
            _sys_usw_stacking_update_non_uc_port(lchip, trunk_id, add_ports, add_ports_num, CTC_MAP_GPORT_TO_LPORT(add_ports[add_loop]), 1);
            MCHIP_LAG_BLOCK_UNLOCK(lchip);
        }

    }
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, trunk_id, cmd, &agg_group), ret, error_proc);
    bk_trunk.max_mem_cnt = mem_ports;
    if (CTC_E_NONE == _sys_usw_stacking_trunk_alloc_mem_base(lchip, &bk_trunk, mem_ports, &mem_base))
    {
        for (loop = 0; loop < mem_ports; loop++)
        {
            dmps_port_info.gport = gports[loop];
            CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id), ret, error_proc);
            fld_val = SYS_USW_CHANNEL_ENCODE(chan_id); /* for TMG, chan bit7 is dpid, bit6 is not use */
            cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
            DRV_FIELD_IOCTL(lchip, bk_trunk.mem_base + loop, cmd, &fld_val);

            fld_val = p_sys_trunk->trunk_id;
            cmd = DRV_IOW(DsLinkAggregateChannel_t, DsLinkAggregateChannel_u1_g2_linkAggregationChannelGroup_f);
            DRV_FIELD_IOCTL(lchip, chan_id, cmd, &fld_val);
        }
        bk_replace_en = 1;
        SetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &agg_group, bk_trunk.mem_base);
        SetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &agg_group, mem_ports);
        cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, trunk_id, cmd, &agg_group), ret, error_proc);
    }

    mem_base = p_sys_trunk->mem_base;
    /*5. replace per port,don't need rollback !!!!!!!!!!!!!!*/
    for (loop = 0; loop < mem_ports; loop++)
    {
        dmps_port_info.gport = gports[loop];
        CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id), ret, error_proc);
        fld_val = SYS_USW_CHANNEL_ENCODE(chan_id); /* for TMG, chan bit7 is dpid, bit6 is not use */
        cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
        DRV_FIELD_IOCTL(lchip, mem_base + loop, cmd, &fld_val);
        fld_val = 0; /*TODO: multi-slices!*/
        cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_sliceId_f);
        DRV_FIELD_IOCTL(lchip, mem_base + loop, cmd, &fld_val);

        fld_val = p_sys_trunk->trunk_id;
        cmd = DRV_IOW(DsLinkAggregateChannel_t, DsLinkAggregateChannel_u1_g2_linkAggregationChannelGroup_f);
        DRV_FIELD_IOCTL(lchip, chan_id, cmd, &fld_val);
    }

    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &agg_group, p_sys_trunk->mem_base);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &agg_group, mem_ports);
    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, trunk_id, cmd, &agg_group), ret, error_proc);

    /*6. set delete ports, change stacking port to normal port*/
    for (del_loop = 0; del_loop < del_ports_num; del_loop++)
    {
        CTC_ERROR_GOTO(_sys_usw_stacking_change_stacking_port(lchip, p_sys_trunk, NULL, del_ports[del_loop], FALSE), ret, error_proc);

        /*set non-uc ports*/
        if (DRV_FROM_TMM(lchip))
        {
            /*linkagg and stacking share same table*/
            MCHIP_LAG_BLOCK_LOCK(lchip);
            _sys_usw_stacking_update_non_uc_port(lchip, trunk_id, NULL, 0, CTC_MAP_GPORT_TO_LPORT(del_ports[del_loop]), 0);
            MCHIP_LAG_BLOCK_UNLOCK(lchip);
        }
    }

    if (DRV_FROM_TMM(lchip) && CTC_FLAG_ISSET(p_sys_trunk->flag, CTC_STACKING_TRUNK_LSH))
    {
        _sys_usw_stacking_update_self_healing(lchip, trunk_id);
    }

    if (!g_stacking_master[lchip]->bind_mcast_en && mem_ports)
    {
        _sys_usw_stacking_all_mcast_bind_en(lchip, 1);
    }
    else if ((1 == g_stacking_master[lchip]->bind_mcast_en)
        && (0 == _sys_usw_stacking_is_trunk_have_member(lchip)))
    {
        _sys_usw_stacking_all_mcast_bind_en(lchip, 0);
    }

    p_sys_trunk->replace_en = 1;
    if (bk_replace_en)
    {
        _sys_usw_stacking_trunk_free_mem_base(lchip, &bk_trunk, bk_trunk.max_mem_cnt, bk_trunk.mem_base);
    }
    return CTC_E_NONE;
error_proc:
    if (bk_replace_en)
    {
        _sys_usw_stacking_trunk_free_mem_base(lchip, &bk_trunk, bk_trunk.max_mem_cnt, bk_trunk.mem_base);
    }
    for (loop = 0; loop < add_loop; loop++)
    {
        _sys_usw_stacking_change_stacking_port(lchip, p_sys_trunk, NULL, add_ports[loop], FALSE);
    }

    /*4. set delete ports  drop en = 1 and switch port to normal port*/
    for (loop = 0; loop < del_loop; loop++)
    {
        _sys_usw_stacking_change_stacking_port(lchip, p_sys_trunk, NULL, del_ports[loop], TRUE);
    }

    return ret;
}

STATIC int32
_sys_usw_stacking_update_load_mode(uint8 lchip, uint8 trunk_id, ctc_stacking_load_mode_t load_mode)
{
    uint8 mem_index                = 0;
    uint32 chan_id                 = 0;
    uint32 cmd                     = 0;
    uint32 index                   = 0;
    uint16 mem_cnt                 = 0;
    uint16 mem_base                = 0;
    uint8 mode                     = 0;
    uint8 old_load_mode            = 0;
    uint8 step                     = 0;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    DsLinkAggregateChannelGroup_m  ds_link_aggregate_sgmac_group;
    DsLinkAggregateChannelMember_m ds_link_aggregate_sgmac_member;
    DsLinkAggregateChannel_m linkagg_channel;
    sys_usw_opf_t opf;
    uint32 value_32 = 0;

    SYS_STK_INIT_CHECK(lchip);

    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);

    if (load_mode >= CTC_STK_LOAD_MODE_MAX)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_STK_LOAD_STATIC_FAILOVER == load_mode && DRV_FROM_TMM(lchip))
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] not support switch to failover \n");
        return CTC_E_INVALID_CONFIG;
    }

    if (CTC_STACKING_TRUNK_MODE_1 != g_stacking_master[lchip]->trunk_mode && !DRV_FROM_TMM(lchip))
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] need switch static/dynmaic when trunk mode 1 \n");
        return CTC_E_INVALID_CONFIG;
    }

    if (CTC_STACKING_TRUNK_MODE_0 == g_stacking_master[lchip]->trunk_mode && DRV_FROM_TMM(lchip))
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] need switch static/dynmaic when trunk mode 1 \n");
        return CTC_E_INVALID_CONFIG;
    }


    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
        return CTC_E_NOT_EXIST;
    }


    if (p_sys_trunk->mode == load_mode)
    {
        return CTC_E_NONE;
    }

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_MEM_BASE;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_TRUNK, 1);
    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(DsLinkAggregateChannelGroup_m));
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group));


    mem_cnt     = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group);
    mode        = GetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group);

    if (mode == 1)
    {
        old_load_mode = CTC_STK_LOAD_DYNAMIC;
    }
    else if(mode == 0)
    {
        old_load_mode = CTC_STK_LOAD_STATIC;
    }

    if (CTC_STK_LOAD_DYNAMIC == load_mode)
    {
        /* static/failover update to dynamic */
        if (mem_cnt > MCHIP_CAP(SYS_CAP_STK_TRUNK_DLB_MAX_MEMBERS))
        {
            return CTC_E_INVALID_CONFIG;
        }

        if (p_sys_trunk->flow_cnt == 0)
        {
            p_sys_trunk->flow_cnt = p_sys_trunk->max_mem_cnt;

            if (DRV_FROM_TMM(lchip))
            {
                CTC_ERROR_RETURN(sys_usw_opf_free_offset(SYS_PP_BASE(lchip), &opf, p_sys_trunk->max_mem_cnt, p_sys_trunk->mem_base));
                p_sys_trunk->max_mem_cnt = 0;
                CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset(SYS_PP_BASE(lchip), DsLagDlbFlowSetTable_t,
                                                                0, p_sys_trunk->flow_cnt, 1, &value_32));
                p_sys_trunk->flow_base= value_32;
            }
            else
            {
                p_sys_trunk->flow_base = p_sys_trunk->mem_base;
            }
        }
        p_sys_trunk->mode = CTC_STK_LOAD_DYNAMIC;

        mem_base = p_sys_trunk->mem_base;
        /* 1.update member to dynamic */
        for (mem_index = 0; mem_index < mem_cnt; mem_index++)
        {
            cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mem_base + mem_index, cmd, &chan_id));

            CTC_ERROR_RETURN(_sys_usw_stacking_dlb_add_member(lchip, trunk_id, mem_index, SYS_USW_CHANNEL_DECODE(chan_id)));
        }

        CTC_ERROR_RETURN(_sys_usw_stacking_clear_flow_active(lchip, trunk_id));


        /* 2.update group to dynamic */
        SetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group, p_sys_trunk->flow_base);
        SetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group, 1);
        SetDsLinkAggregateChannelGroup(V, channelLinkAggFlowNum_f, &ds_link_aggregate_sgmac_group,
                                           _sys_usw_stacking_dlb_flows2driver(lchip, p_sys_trunk->flow_cnt));

        cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group));

    }
    else
    {
        /* dynamic update to static */
        if (mem_cnt > MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS))
        {
            return CTC_E_INVALID_CONFIG;
        }

        if(DRV_FROM_TMM(lchip) && (old_load_mode == CTC_STK_LOAD_DYNAMIC))
        {
            p_sys_trunk->max_mem_cnt = MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS);
            CTC_ERROR_RETURN(sys_usw_ftm_free_table_offset(SYS_PP_BASE(lchip), DsLagDlbFlowSetTable_t, 0, p_sys_trunk->flow_cnt, p_sys_trunk->flow_base));
            p_sys_trunk->flow_cnt = 0;
            CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(SYS_PP_BASE(lchip), &opf, p_sys_trunk->max_mem_cnt, &value_32));
            p_sys_trunk->mem_base = value_32;
        }

        p_sys_trunk->mode = load_mode;

        mem_base = p_sys_trunk->mem_base;

        /* failover/dynamic update to static; static/dynamic update to failover */
        if (old_load_mode == CTC_STK_LOAD_DYNAMIC)
        {
            /* 1.update group to static */
            SetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group, 0);
            SetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group, mem_base);
            cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group));
        }


        step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

        /* 2.update member to static */
        for (mem_index = 0; mem_index < mem_cnt; mem_index++)
        {
            uint32 chan_tmp = 0;
            if (old_load_mode == CTC_STK_LOAD_DYNAMIC)
            {
                cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DsLinkAggregateChannelMemberSet_array_0_channelId_f + mem_index*step);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip,  trunk_id, cmd, &chan_id));
            }
            else
            {
                cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mem_base + mem_index, cmd, &chan_id));
            }
            chan_tmp = SYS_USW_CHANNEL_DECODE(chan_id); /* for TMG, conver 0-255 to 0-127 */

            if (old_load_mode == CTC_STK_LOAD_DYNAMIC)
            {
                sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(ds_link_aggregate_sgmac_member));
                cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
                SetDsLinkAggregateChannelMember(V, channelId_f, &ds_link_aggregate_sgmac_member, chan_id);
                SetDsLinkAggregateChannelMember(V, sliceId_f, &ds_link_aggregate_sgmac_member, 0);
                index = mem_base + mem_index;
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_link_aggregate_sgmac_member));
            }

            if (CTC_STK_LOAD_STATIC == load_mode)  /* failover/dynamic update to static */
            {
                CTC_ERROR_RETURN(_sys_usw_stacking_dlb_del_member_channel(lchip, trunk_id, chan_tmp));
            }
            else if (CTC_STK_LOAD_STATIC_FAILOVER == load_mode) /* static/dynamic update to failover */
            {
                sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));
                cmd = DRV_IOR(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_tmp, cmd, &linkagg_channel));
                SetDsLinkAggregateChannel(V, groupType_f, &linkagg_channel, 1);
                SetDsLinkAggregateChannel(V, groupEn_f, &linkagg_channel, 1);
                SetDsLinkAggregateChannel(V, u1_g2_linkAggregationChannelGroup_f, &linkagg_channel, trunk_id);

                cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_tmp, cmd, &linkagg_channel));
            }
        }
    }


    return CTC_E_NONE;
}

int32
_sys_usw_stacking_set_trunk_mode(uint8 lchip, uint8 mode)
{
    ctc_vector_t* p_trunk_vec = NULL;
    uint32 cflex_sel_mode = 0;
    uint32 cmd = 0;

    SYS_STK_INIT_CHECK(lchip);
    p_trunk_vec = g_stacking_master[lchip]->p_trunk_vec;
    if (!p_trunk_vec)
    {
        return CTC_E_NOT_INIT;
    }

    if (p_trunk_vec->used_cnt)
    {
        return CTC_E_IN_USE;
    }

    switch(mode)
    {
    case CTC_STACKING_TRUNK_MODE_0:
        cflex_sel_mode = 1;
        if (DRV_FROM_TMM(lchip))
        {
            MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = 64;
        }
        break;
    case CTC_STACKING_TRUNK_MODE_1:
        cflex_sel_mode = 2;
        if (DRV_FROM_TMM(lchip))
        {
            MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = 32;
            MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS) = 31;
        }
        break;
    case CTC_STACKING_TRUNK_MODE_2:
        cflex_sel_mode = 1;
        if (DRV_FROM_TMM(lchip))
        {
            MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS) = 15;
            MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = 64;
        }
        break;
    case CTC_STACKING_TRUNK_MODE_3:
        cflex_sel_mode = 0;
        break;
    case CTC_STACKING_TRUNK_MODE_4:
        cflex_sel_mode = 3;
        MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS) = 7;
        MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = 127;
        break;
    case CTC_STACKING_TRUNK_MODE_5:
        cflex_sel_mode = 4;
        MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS) = 63;
        MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = 16;
        break;
    case CTC_STACKING_TRUNK_MODE_6:
        cflex_sel_mode = 5;
        MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS) = 127;
        MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = 8;
        break;
    default:
        return CTC_E_INVALID_PARAM;
    }

    cmd = DRV_IOW(MetFifoCtl_t, MetFifoCtl_mcastToCflexIndexSelMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &cflex_sel_mode));
    cmd = DRV_IOW(MetFifoCtl_t, MetFifoCtl_exceptionToCflexIndexSelMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &cflex_sel_mode));

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER, 1);
    g_stacking_master[lchip]->trunk_mode = mode;

    return CTC_E_NONE;
}

#define ___TRUNK__API___
int32
sys_usw_stacking_create_trunk(uint8 lchip, ctc_stacking_trunk_t * p_trunk)
{
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_trunk);

    if (p_trunk->encap_hdr.vlan_valid)
    {
        CTC_VLAN_RANGE_CHECK(p_trunk->encap_hdr.vlan_id);
    }

    SYS_STK_TRUNKID_RANGE_CHECK(p_trunk->trunk_id);

    if (p_trunk->load_mode >= CTC_STK_LOAD_MODE_MAX)
    {
        return CTC_E_INVALID_PARAM;
    }

    if ((CTC_STACKING_TRUNK_MODE_0 == g_stacking_master[lchip]->trunk_mode)
        && (CTC_STK_LOAD_DYNAMIC == p_trunk->load_mode))
    {
        return CTC_E_INVALID_PARAM;
    }

    if ((CTC_STACKING_TRUNK_MODE_2 == g_stacking_master[lchip]->trunk_mode)
        ||(CTC_STACKING_TRUNK_MODE_3 == g_stacking_master[lchip]->trunk_mode)
        ||(CTC_STACKING_TRUNK_MODE_4 == g_stacking_master[lchip]->trunk_mode)
        ||(CTC_STACKING_TRUNK_MODE_5 == g_stacking_master[lchip]->trunk_mode)
        ||(CTC_STACKING_TRUNK_MODE_6 == g_stacking_master[lchip]->trunk_mode))
    {
        if (CTC_STK_LOAD_DYNAMIC == p_trunk->load_mode)
        {
            if (DRV_FROM_TMM(lchip))
            {
                if (!((p_trunk->max_mem_cnt & (p_trunk->max_mem_cnt - 1)) == 0 &&
                    p_trunk->max_mem_cnt >= CTC_CONST16 && p_trunk->max_mem_cnt <= SYS_STACKING_MAX_DLB_FLOW_NUM))
                {
                    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "dlb member_num invalid!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }
            else
            {
                p_trunk->max_mem_cnt = CTC_CONST32;
            }
        }
        else
        {
            if ((p_trunk->max_mem_cnt > MCHIP_CAP(SYS_CAP_STK_TRUNK_STATIC_MAX_MEMBERS)) ||  0 == p_trunk->max_mem_cnt)
            {
                return CTC_E_INVALID_PARAM;
            }
        }
    }
    if(CTC_FLAG_ISSET(p_trunk->flag, CTC_STACKING_TRUNK_MEM_ASCEND_ORDER) && p_trunk->load_mode != CTC_STK_LOAD_STATIC)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR,"Only static mode support \n");
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_FLAG_ISSET(p_trunk->flag, CTC_STACKING_TRUNK_LB_HASH_OFFSET_VALID))
    {
        CTC_MAX_VALUE_CHECK(p_trunk->lb_hash_offset, (CTC_CONST128-1))
    }

    if (!DRV_IS_DUET2(lchip))
    {
       if(p_trunk->encap_hdr.hdr_flag != CTC_STK_HDR_WITH_NONE &&
        p_trunk->encap_hdr.hdr_flag != CTC_STK_HDR_WITH_L2)
       {
           SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Header encap not support \n");
           return CTC_E_INVALID_PARAM;
       }
    }

    STACKING_LOCK;
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_stacking_create_trunk(lchip, p_trunk), g_stacking_master[lchip]->p_stacking_mutex);
    STACKING_UNLOCK;
    return CTC_E_NONE;
}
int32
sys_usw_stacking_destroy_trunk(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_trunk);
    SYS_STK_TRUNKID_RANGE_CHECK(p_trunk->trunk_id);

    STACKING_LOCK;
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_stacking_destroy_trunk(lchip, p_trunk), g_stacking_master[lchip]->p_stacking_mutex);
    STACKING_UNLOCK;

    return CTC_E_NONE;
}
int32
sys_usw_stacking_add_trunk_port(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint16 lport;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_INIT_CHECK(lchip);

    CTC_PTR_VALID_CHECK(p_trunk);
    SYS_STK_TRUNKID_RANGE_CHECK(p_trunk->trunk_id);

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->gport, lchip, lport);
    SYS_STK_LPORT_CHECK(lport);

    STACKING_LOCK;
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_stacking_add_trunk_port(lchip, p_trunk), g_stacking_master[lchip]->p_stacking_mutex);
    STACKING_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_stacking_remove_trunk_port(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint16 lport;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_trunk);

    SYS_STK_TRUNKID_RANGE_CHECK(p_trunk->trunk_id);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->gport, lchip, lport);
    SYS_STK_LPORT_CHECK(lport);

    STACKING_LOCK;
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_stacking_remove_trunk_port(lchip, p_trunk), g_stacking_master[lchip]->p_stacking_mutex);
    STACKING_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_stacking_replace_trunk_ports(uint8 lchip, uint8 trunk_id, uint32* gports, uint8 mem_ports)
{
    int32 ret = 0;

    SYS_STK_INIT_CHECK(lchip);
    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);
    CTC_PTR_VALID_CHECK(gports);

    STACKING_LOCK;
    ret = _sys_usw_stacking_replace_trunk_ports(lchip, trunk_id, gports, mem_ports);
    STACKING_UNLOCK;

    return ret;
}

int32
sys_usw_stacking_get_member_ports(uint8 lchip, uint8 trunk_id, uint32* p_gports, uint8* cnt)
{
    int32 ret = 0;

    SYS_STK_INIT_CHECK(lchip);
    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);
    CTC_PTR_VALID_CHECK(p_gports);
    CTC_PTR_VALID_CHECK(cnt);

    STACKING_LOCK;
    ret = _sys_usw_stacking_get_member_ports(lchip, trunk_id, p_gports, cnt);
    STACKING_UNLOCK;

    return ret; 
}

int32
sys_usw_stacking_add_trunk_rchip(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    int32 ret                      = 0;
    uint8 trunk_id                 = 0;
    uint8 rgchip                   = 0;
    uint8 gchip                    = 0;
    uint32 index                   = 0;
    ctc_stacking_trunk_t trunk;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    uint32 cmd                     = 0;
    uint32 field_val               = 0;
    uint8 bpe_en                   = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_trunk);
    trunk_id = p_trunk->trunk_id;
    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);
    rgchip    = p_trunk->remote_gchip;
    if (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)
    {
        SYS_STK_CHIPID_CHECK(rgchip);
        SYS_STK_SEL_GRP_CHECK(p_trunk->src_gport, p_trunk->select_mode);
        /*if gchip is local, return */
        if (sys_usw_chip_is_local(lchip, rgchip))
        {
            return CTC_E_NONE;
        }
    }
    else
    {
        if(CTC_MAX_UINT32_VALUE != p_trunk->src_gport)
        {
            SYS_STK_CHIPID_CHECK(rgchip);
        }
        p_trunk->select_mode = 0;
    }
    

    if (p_trunk->select_mode == 1 
        && ((g_stacking_master[lchip]->src_port_mode == SYS_STACKING_SRC_PORT_MODE_GCHIP)
        || (SYS_STACKING_SRC_PORT_MODE_HASH == g_stacking_master[lchip]->src_port_mode)))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (p_trunk->select_mode == 1 && !g_stacking_master[lchip]->src_port_mode)
    {
        uint32 lport = 0;
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->src_gport, lchip, lport);
    }

    CTC_ERROR_RETURN(sys_usw_nh_get_bpe_en(lchip, &bpe_en));
    STACKING_LOCK;

    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
        ret = CTC_E_NOT_EXIST;
		goto unlock;
    }

    if (p_trunk->select_mode == 1)
    {
        if (!g_stacking_master[lchip]->src_port_mode)
        {
            CTC_ERROR_GOTO(_sys_usw_stacking_add_trunk_port_rchip(lchip, p_trunk), ret, unlock);
        }
        else
        {
            index = (p_trunk->src_gport << 7) + p_trunk->remote_gchip;
            field_val = p_trunk->trunk_id;
            cmd = DRV_IOW(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val), ret, unlock);
            SYS_STK_WRITE_SGMAC(lchip, index, field_val);
        }
    }
    else if ((g_stacking_master[lchip]->src_port_mode != SYS_STACKING_SRC_PORT_MODE_GCHIP)
        && (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode))
    {
        uint32 port_type = 0;
        sal_memcpy(&trunk, p_trunk, sizeof(trunk));
        for (index = 0; index < MCHIP_CAP(SYS_CAP_STK_MAX_LPORT); index++)
        {
            sys_usw_get_gchip_id(lchip, &gchip);
            trunk.src_gport =  SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, index);

            dmps_port_info.gport = trunk.src_gport;
            CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type), ret, unlock);
            if ((SYS_DMPS_NETWORK_PORT != port_type) && !bpe_en && (SYS_DMPS_CPUMAC_NETWORK_PORT != port_type))
            {
                continue;
            }

            if (!g_stacking_master[lchip]->src_port_mode)
            {
                CTC_ERROR_GOTO(_sys_usw_stacking_add_trunk_port_rchip(lchip, &trunk), ret, unlock);
            }
            else
            {
                CTC_ERROR_GOTO(sys_usw_port_api_set_property(lchip, trunk.src_gport, CTC_PORT_PROP_STK_GRP_ID, 0), ret, unlock);
            }
        }
    }

    if ((SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode) || (CTC_MAX_UINT32_VALUE == p_trunk->src_gport))
    {
        index = (0 << 7) + p_trunk->remote_gchip;
    }
    else
    {
        index = (1 << 9) + p_trunk->remote_gchip;
    }

    field_val = p_trunk->trunk_id;
    cmd = DRV_IOW(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val), ret, unlock);
    SYS_STK_WRITE_SGMAC(lchip, index, field_val);

    STACKING_UNLOCK;

    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && ((SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)
        || ((SYS_STACKING_SRC_PORT_MODE_HASH == g_stacking_master[lchip]->src_port_mode) && (CTC_MAX_UINT32_VALUE != p_trunk->src_gport))))
    {
        SYS_CB(SYS_CB_MIRROR_UPDATE_TRUNK_BY_RCHIP, lchip, rgchip, trunk_id);
    }

    return CTC_E_NONE;

    unlock:
    STACKING_UNLOCK;
    return ret;
}

int32
sys_usw_stacking_remove_trunk_rchip(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    int32 ret                      = 0;
    uint8 trunk_id                 = 0;
    uint8 rgchip                   = 0;
    uint8 gchip                    = 0;
    uint32 index                   = 0;
    ctc_stacking_trunk_t trunk;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    uint32 cmd                     = 0;
    uint32 field_val               = 0;
    uint8  bpe_en                  = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_trunk);

    trunk_id = p_trunk->trunk_id;
    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);

    rgchip    = p_trunk->remote_gchip;
    if (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)
    {
        SYS_STK_CHIPID_CHECK(rgchip);
        SYS_STK_SEL_GRP_CHECK(p_trunk->src_gport, p_trunk->select_mode);
        /*if gchip is local, return */
        if (sys_usw_chip_is_local(lchip, rgchip))
        {
            return CTC_E_NONE;
        }
    }
    else
    {
        if(CTC_MAX_UINT32_VALUE != p_trunk->src_gport)
        {
            SYS_STK_CHIPID_CHECK(rgchip);
        }
        p_trunk->select_mode = 0;
    }

    if (p_trunk->select_mode == 1 
        && ((g_stacking_master[lchip]->src_port_mode == SYS_STACKING_SRC_PORT_MODE_GCHIP)
        || (SYS_STACKING_SRC_PORT_MODE_HASH == g_stacking_master[lchip]->src_port_mode)))
    {
        return CTC_E_INVALID_PARAM;
    }

    sal_memcpy(&trunk, p_trunk, sizeof(trunk));
    CTC_ERROR_RETURN(sys_usw_stacking_get_trunk_rchip(lchip, &trunk));
    if (trunk.trunk_id != trunk_id)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk id do not match the remote_gchip\n");
        return CTC_E_INVALID_CONFIG;
    }

    if (p_trunk->select_mode == 1 && !g_stacking_master[lchip]->src_port_mode)
    {
        uint32 lport = 0;
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->src_gport, lchip, lport);
    }

    CTC_ERROR_RETURN(sys_usw_nh_get_bpe_en(lchip, &bpe_en));

    STACKING_LOCK;

    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
        ret = CTC_E_NOT_EXIST;
		goto unlock;

    }

    if (p_trunk->select_mode == 1)
    {
        if (!g_stacking_master[lchip]->src_port_mode)
        {
            CTC_ERROR_GOTO(_sys_usw_stacking_remove_trunk_port_rchip(lchip, p_trunk), ret, unlock);
        }
        else
        {
            index = (p_trunk->src_gport << 7) + p_trunk->remote_gchip;
            field_val = 0;
            cmd = DRV_IOW(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val), ret, unlock);
            SYS_STK_WRITE_SGMAC(lchip, index, field_val);
        }
    }
    else if ((g_stacking_master[lchip]->src_port_mode != SYS_STACKING_SRC_PORT_MODE_GCHIP)
        && (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode))
    {
        uint32 port_type = 0;
        sal_memcpy(&trunk, p_trunk, sizeof(trunk));
        for (index = 0; index < MCHIP_CAP(SYS_CAP_STK_MAX_LPORT); index++)
        {
            sys_usw_get_gchip_id(lchip, &gchip);
            if (!g_stacking_master[lchip]->src_port_mode)
            {
                trunk.src_gport =  SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, index);
                dmps_port_info.gport = trunk.src_gport;
                CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type), ret, unlock);
                if ((SYS_DMPS_NETWORK_PORT != port_type) && !bpe_en && (SYS_DMPS_CPUMAC_NETWORK_PORT != port_type))
                {
                    continue;
                }
                CTC_ERROR_GOTO(_sys_usw_stacking_remove_trunk_port_rchip(lchip, &trunk), ret, unlock);
            }
        }
    }

    if ((SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode) || (CTC_MAX_UINT32_VALUE == p_trunk->src_gport))
    {
        index = (0 << 7) + p_trunk->remote_gchip;
    }
    else
    {
        index = (1 << 9) + p_trunk->remote_gchip;
    }

    field_val = 0;
    cmd = DRV_IOW(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val), ret, unlock);
    SYS_STK_WRITE_SGMAC(lchip, index, field_val);

    STACKING_UNLOCK;

    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && ((SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)
        || ((SYS_STACKING_SRC_PORT_MODE_HASH == g_stacking_master[lchip]->src_port_mode) && (CTC_MAX_UINT32_VALUE != p_trunk->src_gport))))
    {
        SYS_CB(SYS_CB_MIRROR_UPDATE_TRUNK_BY_RCHIP, lchip, rgchip, 0);
        sys_usw_update_trunkid_by_rchip(lchip, rgchip, 0);
    }

    return CTC_E_NONE;

    unlock:
    STACKING_UNLOCK;
    return ret;
}


int32
sys_usw_stacking_get_trunk_rchip(uint8 lchip, ctc_stacking_trunk_t* p_trunk)
{
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 field_val = 0;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_trunk);
    if (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)
    {
        SYS_STK_CHIPID_CHECK(p_trunk->remote_gchip);
    }
    else
    {
        if(CTC_MAX_UINT32_VALUE != p_trunk->src_gport)
        {
            SYS_STK_CHIPID_CHECK(p_trunk->remote_gchip);
        }
        p_trunk->select_mode = 0;
    }

    if (p_trunk->select_mode == 1 
        && ((g_stacking_master[lchip]->src_port_mode == SYS_STACKING_SRC_PORT_MODE_GCHIP)
        || (SYS_STACKING_SRC_PORT_MODE_HASH == g_stacking_master[lchip]->src_port_mode)))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (p_trunk->select_mode == 0)
    {
        index = ((SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode) || (CTC_MAX_UINT32_VALUE == p_trunk->src_gport))?p_trunk->remote_gchip:(1 << 9) + p_trunk->remote_gchip;
        cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));
    }
    else
    {
        uint32 port_fwd_sel = 0;
        uint32 lport = 0;
        SYS_STK_SEL_GRP_CHECK(p_trunk->src_gport, p_trunk->select_mode);
        if (!g_stacking_master[lchip]->src_port_mode)
        {
            SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_trunk->src_gport, lchip, lport);
            cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexFwdSgGroupSel_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_fwd_sel));
        }
        else if (1 == g_stacking_master[lchip]->src_port_mode)
        {
            port_fwd_sel = p_trunk->src_gport;
        }

        index = (port_fwd_sel << 7) + p_trunk->remote_gchip;
        cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));


    }

    STACKING_LOCK;

    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, field_val);
    if (NULL == p_sys_trunk)
    {
        STACKING_UNLOCK;
        return CTC_E_STK_TRUNK_NOT_EXIST;
    }

    STACKING_UNLOCK;

    p_trunk->trunk_id = field_val;

    return CTC_E_NONE;
}

/***********************************************************
** LOOP break functions
************************************************************/
#define _____LOOP_BREAK_____ ""


STATIC  int32
_sys_usw_stacking_set_discard_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{
    uint32 cmd       = 0;
    MetFifoCtl_m met_fifo_ctl;
    uint32 field_val[SYS_STK_MAX_GCHIP/CTC_UINT32_BITS] = {0};

    sal_memset(&met_fifo_ctl, 0, sizeof(MetFifoCtl_m));

    cmd = DRV_IOR(MetFifoCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &met_fifo_ctl));

    if (p_stop_rchip->mode == CTC_STK_STOP_MODE_DISCARD_RCHIP_BITMAP)
    {
        GetMetFifoCtl(A, endRemoteChip_f, &met_fifo_ctl, field_val);
        field_val[0] = p_stop_rchip->rchip_bitmap;
        SetMetFifoCtl(A, endRemoteChip_f, &met_fifo_ctl, field_val);
    }
    else if(p_stop_rchip->mode == CTC_STK_STOP_MODE_DISCARD_RCHIP)
    {
        uint32 rgchip = p_stop_rchip->rchip;

        SYS_STK_CHIPID_CHECK(rgchip);

        GetMetFifoCtl(A, endRemoteChip_f, &met_fifo_ctl, field_val);

        if (p_stop_rchip->discard)
        {
            CTC_BIT_SET(field_val[rgchip / 32], rgchip % 32);
        }
        else
        {
            CTC_BIT_UNSET(field_val[rgchip / 32], rgchip % 32);
        }

        SetMetFifoCtl(A, endRemoteChip_f, &met_fifo_ctl, field_val);
    }

    cmd = DRV_IOW(MetFifoCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &met_fifo_ctl));

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_get_discard_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{
    uint32 cmd       = 0;
    uint32 field_val[SYS_STK_MAX_GCHIP/CTC_UINT32_BITS] = {0};
    MetFifoCtl_m met_fifo_ctl;

    sal_memset(&met_fifo_ctl, 0, sizeof(MetFifoCtl_m));

    cmd = DRV_IOR(MetFifoCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &met_fifo_ctl));


    if (p_stop_rchip->mode == CTC_STK_STOP_MODE_DISCARD_RCHIP_BITMAP)
    {
        GetMetFifoCtl(A, endRemoteChip_f, &met_fifo_ctl, field_val);
        p_stop_rchip->rchip_bitmap = field_val[0];
    }
    else if(p_stop_rchip->mode == CTC_STK_STOP_MODE_DISCARD_RCHIP)
    {
        uint32 rgchip = p_stop_rchip->rchip;

        SYS_STK_CHIPID_CHECK(rgchip);

        GetMetFifoCtl(A, endRemoteChip_f, &met_fifo_ctl, field_val);

        p_stop_rchip->discard =  CTC_IS_BIT_SET(field_val[rgchip / 32], rgchip % 32);
    }



    return CTC_E_NONE;
}

STATIC  int32
_sys_usw_stacking_set_discard_port_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{
    uint32 cmd                     = 0;
    uint32 lport                   = 0;
    uint32 index                   = 0;
    uint32 bitmap[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    DsCFlexSrcPortBlockMask_m block;

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_stop_rchip);

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_stop_rchip->src_gport, lchip, lport);
    SYS_STK_LPORT_CHECK(lport);
    SYS_STK_CHIPID_CHECK(p_stop_rchip->rchip);

    index = p_stop_rchip->rchip;

    sal_memset(&block, 0, sizeof(block));
    cmd = DRV_IOR(DsCFlexSrcPortBlockMask_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &block));
    GetDsCFlexSrcPortBlockMask(A, srcPortBitMap_f, &block, bitmap);

    if (p_stop_rchip->discard)
    {
        CTC_BMP_SET(bitmap, lport);
    }
    else
    {
        CTC_BMP_UNSET(bitmap, lport);
    }

    SetDsCFlexSrcPortBlockMask(A, srcPortBitMap_f, &block, bitmap);


    cmd = DRV_IOW(DsCFlexSrcPortBlockMask_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &block));

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_get_discard_port_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{
    uint32 cmd                     = 0;
    uint32 lport                   = 0;
    uint32 index                   = 0;
    uint32 bitmap[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
    DsCFlexSrcPortBlockMask_m block;

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_stop_rchip);

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_stop_rchip->src_gport, lchip, lport);
    SYS_STK_LPORT_CHECK(lport);
    SYS_STK_CHIPID_CHECK(p_stop_rchip->rchip);

    index = p_stop_rchip->rchip;

    sal_memset(&block, 0, sizeof(block));
    cmd = DRV_IOR(DsCFlexSrcPortBlockMask_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &block));
    GetDsCFlexSrcPortBlockMask(A, srcPortBitMap_f, &block, bitmap);

    if (CTC_BMP_ISSET(bitmap, lport))
    {
        p_stop_rchip->discard = 1;
    }

    return CTC_E_NONE;
}
/*****************************************************************
Before TM:
|mode | chip num| profile num|port num| chip shift| profile shift |
|  1  | 128     |      8     |   64   |     3     |       0       |
|  2  | 128     |      4     |   128  |     3     |       1       |
|  3  | 128     |      2     |   256  |     3     |       2       |
|  4  | 64      |      8     |   128  |     4     |       1       |
|  5  | 64      |      4     |   256  |     4     |       2       |
TM.MX:
|mode | chip num| profile num|port num| chip shift| profile shift |
|  1  | 128     |      8     |   128  |     4     |       1       |
|  2  | 64      |      8     |   256  |     5     |       2       |
|  3  | 128     |      4     |   256  |     4     |       2       |
Arctic:
|mode | chip num| profile num|port num| chip shift| profile shift |
|  1  | 128     |      8     |   256  |     5     |       2       |
|  2  | 64      |      8     |   512  |     6     |       3       |
|  3  | 128     |      4     |   512  |     5     |       3       |

*******************************************************************/
STATIC int32
_sys_usw_stacking_get_isolation_info(uint8 lchip, uint8* p_chip_shift, uint8*p_profile_shift, uint8*p_profile_num)
{
    /*profile num, chip shift, profile shift*/
    uint8 before_tm_mx_isolation_info[][3] = {
                        {0, 0, 0},
                        {8, 3, 0},
                        {4, 3, 1},
                        {2, 3, 2},
                        {8, 4, 1},
                        {4, 4, 2}};
    uint8 tm_mx_isolation_info[][3] = {
                        {0, 0, 0},
                        {8, 4, 1},
                        {8, 5, 2},
                        {4, 4, 2}};
    uint8 at_isolation_info[][3] = {
                        {0, 0, 0},
                        {8, 5, 2},
                        {8, 6, 3},
                        {4, 5, 3}};

    if (DRV_FROM_AT(lchip))
    {
        *p_profile_num = at_isolation_info[g_stacking_master[lchip]->isolation_mode][0];
        *p_chip_shift = at_isolation_info[g_stacking_master[lchip]->isolation_mode][1];
        *p_profile_shift = at_isolation_info[g_stacking_master[lchip]->isolation_mode][2];
    }
    else if(DRV_FROM_TMM(lchip))
    {
        *p_profile_num = tm_mx_isolation_info[g_stacking_master[lchip]->isolation_mode][0];
        *p_chip_shift = tm_mx_isolation_info[g_stacking_master[lchip]->isolation_mode][1];
        *p_profile_shift = tm_mx_isolation_info[g_stacking_master[lchip]->isolation_mode][2];
    }
    else
    {
        *p_profile_num = before_tm_mx_isolation_info[g_stacking_master[lchip]->isolation_mode][0];
        *p_chip_shift = before_tm_mx_isolation_info[g_stacking_master[lchip]->isolation_mode][1];
        *p_profile_shift = before_tm_mx_isolation_info[g_stacking_master[lchip]->isolation_mode][2];
    }
    return CTC_E_NONE;
}

STATIC  int32
_sys_usw_stacking_set_block_port_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{
    uint32 cmd                     = 0;
    uint32 index                   = 0;
    uint8  loop_chip = 0;
    uint8  loop_chip_end = 0;
    uint8  profile_id = 0;
    uint16 lport;
    sys_stacking_block_profile_t*  p_profile_get = NULL;
    uint8 loop;
    uint8 loop_max;
    uint32 chan_id = 0;
    uint32 bitmap[SYS_STK_MAX_LPORT_IN_WORD] = {0};
    uint8 gchip = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
	uint32 chan_tmp = 0;
	
    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_stop_rchip);
    SYS_STK_CHIPID_CHECK(p_stop_rchip->rchip);

    sys_usw_get_gchip_id(lchip, &gchip);
    /*check channel id exceed max port id*/
    for (index = 0; index < MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP); index++)
    {
        if (!CTC_BMP_ISSET(p_stop_rchip->pbm, index))
        {
            continue;
        }

        dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, index);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
		chan_tmp = SYS_USW_CHANNEL_DECODE(chan_id); /* for TMG, chan bit7 is dpid, bit6 is not use */
        if ((SYS_DMPS_INVALID_CHAN_ID == chan_tmp) || (!SYS_IS_NETWORK_CHANNEL(chan_tmp)) || (chan_tmp > g_stacking_master[lchip]->max_block_port_id))
        {
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "block port id may exceed max port or invalid port! chan_id:%u, max_port:%u \n", chan_id, g_stacking_master[lchip]->max_block_port_id);
            return CTC_E_INVALID_CONFIG;
        }

        CTC_BMP_SET(bitmap, chan_tmp);
    }

    /*if src_gport equal CTC_MAX_UINT32_VALUE, set profile 0 remote_chip */
    if (CTC_MAX_UINT32_VALUE == p_stop_rchip->src_gport)
    {
        loop_chip = p_stop_rchip->rchip;
        loop_chip_end = p_stop_rchip->rchip;
    }
    else
    {
        CTC_ERROR_RETURN(_sys_usw_stacking_add_block_port_profile(lchip, p_stop_rchip, &p_profile_get));
        loop_chip = 0;
        loop_chip_end = g_stacking_master[lchip]->max_gchip_id;
        profile_id = p_profile_get->profile_id;
    }

    for(; loop_chip <= loop_chip_end; loop_chip++)
    {
        /*In hw table, one entry store 64 ports bitmap*/
        loop_max = (g_stacking_master[lchip]->max_block_port_id + SYS_STACKING_BLOCK_PORT_UINT) >> 6;
        cmd = DRV_FROM_AT(lchip)? DRV_IOW(DsMcQWriteCFlexDstChannelBlockMask_t, DsMcQWriteCFlexDstChannelBlockMask_dstPortBitMap_f):
        DRV_IOW(DsCFlexDstChannelBlockMask_t, DsCFlexDstChannelBlockMask_dstPortBitMap_f);
        for(loop=0; loop < loop_max; loop++)
        {
            SYS_USW_STK_ENCODE_BLOCK_INDEX(lchip,loop_chip, profile_id, loop, index);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &bitmap[loop<<1]));
        }
    }

    if (CTC_MAX_UINT32_VALUE != p_stop_rchip->src_gport)
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_stop_rchip->src_gport, lchip, lport);
        CTC_ERROR_RETURN(sys_usw_port_set_internal_property(lchip, p_stop_rchip->src_gport, SYS_PORT_PROP_FLEX_DST_ISOLATEGRP_SEL, p_profile_get->profile_id));
    }
    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_get_block_port_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{
    uint32 cmd                     = 0;
    uint32 lport                   = 0;
    uint32 port_block_sel          = 0;
	sys_stacking_block_profile_t* p_profile_get = NULL;
    uint8 loop = 0;
    uint8 loop_max = 0;
    uint8 profile_id = 0;
    uint32 index = 0;
    uint32 old_bitmap[SYS_STK_MAX_LPORT_IN_WORD] = {0};

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_stop_rchip);
    SYS_STK_CHIPID_CHECK(p_stop_rchip->rchip);

    if (CTC_MAX_UINT32_VALUE == p_stop_rchip->src_gport)
    {
        profile_id = 0;
    }
    else
    {
        SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_stop_rchip->src_gport, lchip, lport);
        SYS_STK_LPORT_CHECK(lport);
        cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexDstIsolateGroupSel_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_block_sel));
        p_profile_get = g_stacking_master[lchip]->p_block_profile[port_block_sel];
        if (p_profile_get)
        {
            profile_id = p_profile_get->profile_id;
        }
    }

    sal_memset(p_stop_rchip->pbm, 0, sizeof(p_stop_rchip->pbm));
    /*In hw table, one entry store 64 ports bitmap*/
    loop_max = (g_stacking_master[lchip]->max_block_port_id+SYS_STACKING_BLOCK_PORT_UINT) >> 6;        
    cmd = DRV_FROM_AT(lchip)? DRV_IOR(DsMcQWriteCFlexDstChannelBlockMask_t, DsMcQWriteCFlexDstChannelBlockMask_dstPortBitMap_f):
    DRV_IOR(DsCFlexDstChannelBlockMask_t, DsCFlexDstChannelBlockMask_dstPortBitMap_f);
    for(loop=0; loop < loop_max; loop++)
    {
        SYS_USW_STK_ENCODE_BLOCK_INDEX(lchip, p_stop_rchip->rchip, profile_id, loop, index);           
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &old_bitmap[loop<<1]));
    }

    for (index = 0; index < MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP); index++)
    {
        if (!CTC_BMP_ISSET(old_bitmap, index))
        {
            continue;
        }
        lport = sys_usw_port_api_get_lport_with_chan(lchip, 0, index);
        CTC_BMP_SET(p_stop_rchip->pbm, lport);
    }

    return CTC_E_NONE;
}

STATIC  int32
_sys_usw_stacking_set_stop_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{

    switch(p_stop_rchip->mode)
    {
    case CTC_STK_STOP_MODE_DISCARD_RCHIP_BITMAP:
    case CTC_STK_STOP_MODE_DISCARD_RCHIP:
        CTC_ERROR_RETURN(_sys_usw_stacking_set_discard_rchip(lchip, p_stop_rchip));
        break;

    case CTC_STK_STOP_MODE_DISCARD_RCHIP_PORT:
        CTC_ERROR_RETURN(_sys_usw_stacking_set_discard_port_rchip(lchip, p_stop_rchip));
        break;

    case CTC_STK_STOP_MODE_BLOCK_RCHIP_PORT:
        CTC_ERROR_RETURN(_sys_usw_stacking_set_block_port_rchip(lchip, p_stop_rchip));
        break;

    default:
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_get_stop_rchip(uint8 lchip, ctc_stacking_stop_rchip_t *p_stop_rchip)
{
    switch(p_stop_rchip->mode)
    {
    case CTC_STK_STOP_MODE_DISCARD_RCHIP_BITMAP:
    case CTC_STK_STOP_MODE_DISCARD_RCHIP:
        CTC_ERROR_RETURN(_sys_usw_stacking_get_discard_rchip(lchip, p_stop_rchip));
        break;

    case CTC_STK_STOP_MODE_DISCARD_RCHIP_PORT:
        CTC_ERROR_RETURN(_sys_usw_stacking_get_discard_port_rchip(lchip, p_stop_rchip));
        break;

    case CTC_STK_STOP_MODE_BLOCK_RCHIP_PORT:
        CTC_ERROR_RETURN(_sys_usw_stacking_get_block_port_rchip(lchip, p_stop_rchip));
        break;

    default:
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_set_break_en(uint8 lchip, uint32 enable)
{
    uint32 cmd       = 0;
    uint32 field_val = 0;

    field_val = enable;
    cmd = DRV_IOW(MetFifoCtl_t, MetFifoCtl_stackingBroken_f);

    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_get_break_en(uint8 lchip, uint32* enable)
{
    uint32 cmd       = 0;
    uint32 field_val = 0;

    cmd = DRV_IOR(MetFifoCtl_t, MetFifoCtl_stackingBroken_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    *enable = field_val;

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_set_full_mesh_en(uint8 lchip, uint32 enable)
{
    uint32 cmd       = 0;
    uint32 field_val = 0;

    field_val = enable ? 0 : 1;
    cmd = DRV_IOW(MetFifoCtl_t, MetFifoCtl_forceReplicationFromFabric_f);

    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_get_full_mesh_en(uint8 lchip, uint32* enable)
{
    uint32 cmd       = 0;
    uint32 field_val = 0;

    cmd = DRV_IOR(MetFifoCtl_t, MetFifoCtl_forceReplicationFromFabric_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    *enable = field_val ? 0 : 1;

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_set_global_cfg(uint8 lchip, ctc_stacking_glb_cfg_t* p_glb_cfg)
{

    CTC_ERROR_RETURN(_sys_usw_stacking_hdr_set(lchip, &p_glb_cfg->hdr_glb));

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_get_global_cfg(uint8 lchip, ctc_stacking_glb_cfg_t* p_glb_cfg)
{

    CTC_ERROR_RETURN(_sys_usw_stacking_hdr_get(lchip, &p_glb_cfg->hdr_glb));

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_stacking_set_break_trunk_id(uint8 lchip, ctc_stacking_mcast_break_point_t *p_break_point)
{
    uint32 cmd = 0;
    MetFifoCtl_m met_fifo_ctl;
    uint32 source_bitmap[CTC_STK_TRUNK_BMP_NUM] = {0};

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_break_point);
    SYS_STK_TRUNKID_RANGE_CHECK(p_break_point->trunk_id)

    sal_memset(&met_fifo_ctl, 0, sizeof(met_fifo_ctl));
    cmd = DRV_IOR(MetFifoCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &met_fifo_ctl));
    GetMetFifoCtl(A, sgmacDiscardSourceReplication_f, &met_fifo_ctl, source_bitmap);

    /*set over 63, not work*/
    if (p_break_point->enable)
    {
        CTC_BIT_SET(source_bitmap[p_break_point->trunk_id/CTC_UINT32_BITS], (p_break_point->trunk_id%CTC_UINT32_BITS));
    }
    else
    {
        CTC_BIT_UNSET(source_bitmap[p_break_point->trunk_id/CTC_UINT32_BITS], (p_break_point->trunk_id%CTC_UINT32_BITS));
    }

    SetMetFifoCtl(A, sgmacDiscardSourceReplication_f, &met_fifo_ctl, source_bitmap);
    cmd = DRV_IOW(MetFifoCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &met_fifo_ctl));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_map_gport(uint8 lchip, uint32 gport, uint16* p_index)
{
    uint16 lport                   = 0;
    uint8 rchip                    = 0;
    uint32 min                     = 0;
    uint32 max                     = 0;
    uint32 base                    = 0;
    uint32 cmd                     = 0;
    DsGlbDestPortMap_m port_map;

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_index);

    rchip = CTC_MAP_GPORT_TO_GCHIP(gport);
    lport = CTC_MAP_GPORT_TO_LPORT(gport);

    SYS_STK_CHIPID_CHECK(rchip);


    cmd = DRV_IOR(DsGlbDestPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, rchip, cmd, &port_map));

    base = GetDsGlbDestPortMap(V, glbDestPortBase_f, &port_map);
    min  = GetDsGlbDestPortMap(V, glbDestPortMin_f, &port_map);
    max  = GetDsGlbDestPortMap(V, glbDestPortMax_f, &port_map);

    if ( lport > max  ||  lport < min)
    {
        return CTC_E_INVALID_CHIP_ID;
    }

    *p_index = base + lport;

     return CTC_E_NONE;

}

STATIC int32
_sys_usw_stacking_alloc_glb_destport(uint8 lchip, uint16 max_lport, ctc_stacking_rchip_port_t * p_rchip_port)
{
    int32  ret                     = 0;
    uint32 base                    = 0;
    uint32 max                     = 0;
    uint32 min                     = 0;
    uint32 cmd                     = 0;
    uint16 loop1                   = 0;
    sys_usw_opf_t  opf;

    if (g_stacking_master[lchip]->stacking_ver == CTC_STACKING_VERSION_1_0)
    {
        return CTC_E_NONE;
    }

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_ABILITY;
    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, max_lport + 1, &base));

    SYS_STK_DBG_INFO("Alloc glbDestPortBase :%d, num:%d\n", base,  max_lport + 1);
    cmd = DRV_IOW(DsGlbDestPortMap_t, DsGlbDestPortMap_glbDestPortBase_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, p_rchip_port->rchip, cmd, &base), ret, Error0);

    for (loop1 = 0; loop1 <= max_lport; loop1++)
    {
        CTC_ERROR_GOTO(sys_usw_port_api_glb_dest_port_init(lchip, loop1 + base), ret, Error0);
    }

    min = 0;
    max = max_lport;
    cmd = DRV_IOW(DsGlbDestPortMap_t, DsGlbDestPortMap_glbDestPortMin_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_rchip_port->rchip, cmd, &min));
    cmd = DRV_IOW(DsGlbDestPortMap_t, DsGlbDestPortMap_glbDestPortMax_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_rchip_port->rchip, cmd, &max));
    return CTC_E_NONE;


    Error0:
    sys_usw_opf_free_offset(lchip, &opf, max_lport + 1, base);
    return ret;

}

STATIC int32
_sys_usw_stacking_free_glb_destport(uint8 lchip, uint16 max_lport, ctc_stacking_rchip_port_t * p_rchip_port, uint8 is_update)
{
    sys_usw_opf_t  opf;
    uint32 base                    = 0;
    uint32 max                     = 0;
    uint32 min                     = 0;
    uint32 cmd                     = 0;

    if (g_stacking_master[lchip]->stacking_ver == CTC_STACKING_VERSION_1_0)
    {
        return CTC_E_NONE;
    }

    cmd = DRV_IOR(DsGlbDestPortMap_t, DsGlbDestPortMap_glbDestPortBase_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_rchip_port->rchip, cmd, &base));

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type  = g_stacking_master[lchip]->opf_type;
    opf.pool_index = SYS_STK_OPF_ABILITY;
    SYS_STK_DBG_INFO("Free glbDestPortBase :%d num:%d\n", base, max_lport + 1);

    CTC_ERROR_RETURN(sys_usw_opf_free_offset(lchip, &opf, max_lport + 1, base));

    if(!is_update)
    {
        min = 1;
        max = 0;
        cmd = DRV_IOW(DsGlbDestPortMap_t, DsGlbDestPortMap_glbDestPortMin_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_rchip_port->rchip, cmd, &min));
        cmd = DRV_IOW(DsGlbDestPortMap_t, DsGlbDestPortMap_glbDestPortMax_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_rchip_port->rchip, cmd, &max));
        base = 0;
        cmd = DRV_IOW(DsGlbDestPortMap_t, DsGlbDestPortMap_glbDestPortBase_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_rchip_port->rchip, cmd, &base));
    }
    return CTC_E_NONE;

}

STATIC int32
_sys_usw_stacking_set_rchip_port(uint8 lchip, ctc_stacking_rchip_port_t * p_rchip_port)
{
    uint16 loop1                   = 0;
    uint16 loop2                   = 0;
    uint16 lport                   = 0;
    uint16 max_lport               = 0;
    uint32 gport                   = 0;
    uint8 gchip_id                 = 0;
	uint32 cmd                     = 0;
    uint16 old_glb_max             = 0;
    DsGlbDestPortMap_m             port_map;
    uint16 old_rsv_num             = 0;
    uint16 max_port_num_slice[SYS_USW_RCHIP_SLICE_NUM]  = {0};
    uint16 rsv_num                 = 0;
    uint8  rchip_slice_en          = 0;
    IpeLearningCtl_m         lrn_ctl;
    int32  ret = 0;

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_rchip_port);
    SYS_STK_CHIPID_CHECK(p_rchip_port->rchip);

    sys_usw_get_gchip_id(lchip, &gchip_id);

    if (p_rchip_port->rchip == gchip_id)
    {
        return CTC_E_NONE;
    }

    for (loop1 = 0; loop1 < sizeof(ctc_port_bitmap_t) / sizeof(uint32); loop1++)
    {
        for (loop2 = 0; loop2 < CTC_UINT32_BITS; loop2++)
        {
            lport = loop1 * CTC_UINT32_BITS + loop2;

            gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(p_rchip_port->rchip, lport);

            if (CTC_IS_BIT_SET(p_rchip_port->pbm[loop1], loop2))
            {
                max_lport = lport > max_lport?lport: max_lport;
                max_port_num_slice[lport/SYS_USW_RCHIP_SLICE_PORT_NUM] = (lport % SYS_USW_RCHIP_SLICE_PORT_NUM) + 1;
                ret = sys_usw_brguc_nh_create(lchip, gport, CTC_NH_PARAM_BRGUC_SUB_TYPE_BASIC);
                if(ret && ret != CTC_E_EXIST)
                {
                    return ret;
                }
            }
            else
            {
                sys_usw_brguc_nh_delete(lchip, gport);
            }
        }
    }

    cmd = DRV_IOR(DsGlbDestPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_rchip_port->rchip, cmd, &port_map));
    old_glb_max = GetDsGlbDestPortMap(V, glbDestPortMax_f, &port_map);

    cmd = DRV_IOR(IpeLearningCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lrn_ctl));

    CTC_ERROR_RETURN(sys_usw_l2_get_rchip_rsv_ad(lchip, p_rchip_port->rchip, &old_rsv_num));

    if ((max_port_num_slice[0] == 0) || (max_port_num_slice[1] == 0))
    {
        rsv_num = max_port_num_slice[(max_port_num_slice[0] >= max_port_num_slice[1]) ? 0 : 1];
    }
    else
    {
        /*rsv_num = double max port of one slice if has slice1 port*/
        rsv_num = max_port_num_slice[(max_port_num_slice[0] >= max_port_num_slice[1]) ? 0 : 1] * SYS_USW_RCHIP_SLICE_NUM;
    }

    if (max_port_num_slice[0])
    {
        CTC_BIT_SET(rchip_slice_en, 0);
    }
    if (max_port_num_slice[1])
    {
        CTC_BIT_SET(rchip_slice_en, 1);
    }

    if (GetIpeLearningCtl(V, learningOnStacking_f, &lrn_ctl) && max_lport)
    {
        rsv_num = max_lport + 1;
    }

    if (old_rsv_num)
    {
        sys_usw_l2_free_rchip_ad_index(lchip, p_rchip_port->rchip, old_rsv_num);
    }

    if (old_glb_max)
    {
        _sys_usw_stacking_free_glb_destport(lchip, old_glb_max, p_rchip_port, rsv_num ? 1:0);
    }

    if (rsv_num)
    {
        CTC_ERROR_RETURN(sys_usw_l2_reserve_rchip_ad_index(lchip, p_rchip_port->rchip, rsv_num, rchip_slice_en));
        CTC_ERROR_GOTO(_sys_usw_stacking_alloc_glb_destport(lchip, max_lport, p_rchip_port), ret, error_0);
    }

    return CTC_E_NONE;
error_0:
    sys_usw_l2_free_rchip_ad_index(lchip, p_rchip_port->rchip, rsv_num);
    return ret;

}

STATIC int32
_sys_usw_stacking_get_rchip_port(uint8 lchip, ctc_stacking_rchip_port_t* p_rchip_port)
{
    uint32 cmd                     = 0;
    uint8 gchip_id                 = 0;
    DsGlbDestPortMap_m port_map;
    uint16 max                     = 0;
    uint16 min                     = 0;
    uint16 loop1                   = 0;

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_rchip_port);
    SYS_STK_CHIPID_CHECK(p_rchip_port->rchip);

    sys_usw_get_gchip_id(lchip, &gchip_id);
    if (p_rchip_port->rchip == gchip_id)
    {
        return CTC_E_NONE;
    }

    cmd = DRV_IOR(DsGlbDestPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_rchip_port->rchip, cmd, &port_map));

    max    = GetDsGlbDestPortMap(V, glbDestPortMax_f, &port_map);
    min    = GetDsGlbDestPortMap(V, glbDestPortMin_f, &port_map);


    for (loop1 = min; loop1 < max + 1; loop1++)
    {
        CTC_BMP_SET(p_rchip_port->pbm, loop1);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_binding_trunk(uint8 lchip, uint32 gport, uint8 trunk_id)/*trunk_id = 0 means unbinding*/
{
    uint32 field_val = 0;
    uint32 chan_id = 0;
    uint32 cmd = 0;
    uint32 lport = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STK_INIT_CHECK(lchip);
    if ((trunk_id > MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID)) ||
        ((g_stacking_master[lchip]->trunk_mode == CTC_STACKING_TRUNK_MODE_1) && (trunk_id >= MCHIP_CAP(SYS_CAP_STK_TRUNK_MEMBERS)/CTC_UINT32_BITS)))
    {
        return CTC_E_INVALID_PARAM;
    }
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (SYS_DMPS_INVALID_CHAN_ID == chan_id)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid port \n");
        return CTC_E_INVALID_PORT;
    }

    field_val = trunk_id;
    cmd = DRV_IOW(DsSrcSgmacGroup_t, DsSrcSgmacGroup_sgmacGroupId_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
    g_stacking_master[lchip]->binding_trunk = 1; /*change to 1 once call by user*/

    return CTC_E_NONE;
}

int32
sys_usw_stacking_get_binding_trunk(uint8 lchip, uint32 gport, uint8* trunk_id)/*trunk_id = 0 means unbinding*/
{
    uint32 field_val = 0;
    uint32 chan_id = 0;
    uint32 cmd = 0;
    uint32 lport = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STK_INIT_CHECK(lchip);

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (SYS_DMPS_INVALID_CHAN_ID == chan_id)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid port \n");
        return CTC_E_INVALID_PORT;
    }

    cmd = DRV_IOR(DsSrcSgmacGroup_t, DsSrcSgmacGroup_sgmacGroupId_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
    *trunk_id = field_val;

    return CTC_E_NONE;
}


int32
sys_usw_stacking_set_property(uint8 lchip, ctc_stacking_property_t* p_prop)
{
    int32 ret    = 0;
    uint8 recover_quque = 0;
    sys_qos_shape_profile_t shp_profile;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    ctc_stacking_lb_hash_offset_t* p_lb_hash_offset = NULL;
    DsLinkAggregateChannelGroup_m ds_link_aggregate_sgmac_group;
    uint32 gport = 0;
    uint32 cmd = 0;
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_prop);

    if (CTC_STK_PROP_LB_HASH_OFFSET == p_prop->prop_type)
    {
        CTC_PTR_VALID_CHECK(p_prop->p_value);
        p_lb_hash_offset = (ctc_stacking_lb_hash_offset_t*)p_prop->p_value;
        CTC_MAX_VALUE_CHECK(p_lb_hash_offset->value, (CTC_CONST128-1));
        SYS_STK_TRUNKID_RANGE_CHECK(p_lb_hash_offset->trunk_id);
    }


    STACKING_LOCK;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER, 1);
    switch (p_prop->prop_type)
    {

    case CTC_STK_PROP_GLOBAL_CONFIG:
        {
            ctc_stacking_glb_cfg_t* p_glb_cfg = NULL;
            p_glb_cfg = (ctc_stacking_glb_cfg_t *)p_prop->p_value;
            CTC_ERROR_GOTO(_sys_usw_stacking_set_global_cfg(lchip, p_glb_cfg), ret, unlock);
        }
        break;

    case CTC_STK_PROP_MCAST_STOP_RCHIP:
        {
            ctc_stacking_stop_rchip_t* p_stop_rchip = NULL;
            p_stop_rchip = (ctc_stacking_stop_rchip_t *)p_prop->p_value;
            CTC_ERROR_GOTO(_sys_usw_stacking_set_stop_rchip(lchip, p_stop_rchip), ret, unlock);
        }
        break;

    case CTC_STK_PROP_BREAK_EN:
        CTC_ERROR_GOTO(_sys_usw_stacking_set_break_en(lchip, p_prop->value), ret, unlock);
        break;

    case CTC_STK_PROP_FULL_MESH_EN:
        CTC_ERROR_GOTO(_sys_usw_stacking_set_full_mesh_en(lchip, p_prop->value), ret, unlock);
        break;

    case CTC_STK_PROP_MCAST_BREAK_POINT:
        {
            ctc_stacking_mcast_break_point_t *p_break_point = NULL;
            p_break_point = (ctc_stacking_mcast_break_point_t *)p_prop->p_value;
            CTC_ERROR_GOTO(_sys_usw_stacking_set_break_trunk_id(lchip, p_break_point), ret, unlock);
        }
        break;

    case CTC_STK_PROP_PORT_BIND_TRUNK:
        {
            ctc_stacking_bind_trunk_t *p_bind_trunk = NULL;
            p_bind_trunk = (ctc_stacking_bind_trunk_t *)p_prop->p_value;
            if(!p_bind_trunk)
            {
                STACKING_UNLOCK;
                return CTC_E_INVALID_PTR;
            }
            CTC_ERROR_GOTO(_sys_usw_stacking_binding_trunk(lchip, p_bind_trunk->gport, p_bind_trunk->trunk_id), ret, unlock);
        }
        break;

    case CTC_STK_PROP_RCHIP_PORT_EN:
        {
            ctc_stacking_rchip_port_t *p_rchip_port = NULL;
            p_rchip_port = (ctc_stacking_rchip_port_t *)p_prop->p_value;
            CTC_ERROR_GOTO(_sys_usw_stacking_set_rchip_port(lchip, p_rchip_port), ret, unlock);
        }
        break;
    case CTC_STK_PROP_STK_PORT_EN:
        {
            ctc_stacking_port_cfg_t* p_stk_port;
            ctc_stacking_hdr_encap_t hdr_encap;
            uint32 rx_chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
            uint32 tx_chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
            uint16 gchip = 0;
            uint8 rx_chan_num = 0;
            uint8 tx_chan_num = 0;
            uint8 index = 0;
            p_stk_port = (ctc_stacking_port_cfg_t *)p_prop->p_value;
            if ((p_stk_port->direction > CTC_BOTH_DIRECTION) || (p_stk_port->hdr_type > CTC_STK_HDR_WITH_IPV6))
            {
                STACKING_UNLOCK;
    			return CTC_E_INVALID_PARAM;
            }
            gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_stk_port->gport);
            if (!sys_usw_chip_is_local(lchip, gchip))
            {
                STACKING_UNLOCK;
                return CTC_E_INVALID_CHIP_ID;
            }

            sal_memset(&hdr_encap, 0, sizeof(ctc_stacking_hdr_encap_t));
            sal_memset(&shp_profile, 0, sizeof(sys_qos_shape_profile_t));
            hdr_encap.hdr_flag = p_stk_port->hdr_type;
            gport = p_stk_port->gport;
            CTC_ERROR_GOTO(sys_usw_port_api_get_channel(lchip, 0, gport, tx_chan_id, &tx_chan_num), ret, unlock);
            CTC_ERROR_GOTO(sys_usw_port_api_get_channel(lchip, 1, gport, rx_chan_id, &rx_chan_num), ret, unlock);
            if (p_stk_port->enable)
            {
                if ((p_stk_port->direction == CTC_EGRESS) || (p_stk_port->direction == CTC_BOTH_DIRECTION))
                {
                    CTC_ERROR_GOTO( sys_usw_queue_get_profile_from_hw(lchip, p_stk_port->gport, &shp_profile), ret, unlock);
                    CTC_ERROR_GOTO(sys_usw_queue_set_port_drop_en(lchip, p_stk_port->gport, 1, &shp_profile), ret, unlock);
                    recover_quque = 1;
                    CTC_ERROR_GOTO(_sys_usw_stacking_check_port_status(lchip, p_stk_port->gport, &shp_profile), ret, unlock);
                    for (index = 0; index < tx_chan_num; index++)
                    {
                        CTC_ERROR_GOTO(_sys_usw_stacking_encap_header_enable(lchip, tx_chan_id[index], &hdr_encap, CTC_EGRESS), ret, unlock);
                    }
                    CTC_ERROR_GOTO(sys_usw_queue_set_port_drop_en(lchip, p_stk_port->gport, 0, &shp_profile), ret, unlock);
                    recover_quque = 0;
                    CTC_BMP_SET(g_stacking_master[lchip]->egr_port_en_bmp, CTC_MAP_GPORT_TO_LPORT(p_stk_port->gport));
                }
                if ((p_stk_port->direction == CTC_INGRESS) || (p_stk_port->direction == CTC_BOTH_DIRECTION))
                {
                    for (index = 0; index < rx_chan_num; index++)
                    {
                        CTC_ERROR_GOTO(_sys_usw_stacking_encap_header_enable(lchip, rx_chan_id[index], &hdr_encap, CTC_INGRESS), ret, unlock);
                    }
                    CTC_BMP_SET(g_stacking_master[lchip]->ing_port_en_bmp, CTC_MAP_GPORT_TO_LPORT(p_stk_port->gport));
                }
            }
            else
            {
                if ((p_stk_port->direction == CTC_EGRESS) || (p_stk_port->direction == CTC_BOTH_DIRECTION))
                {
                    CTC_ERROR_GOTO( sys_usw_queue_get_profile_from_hw(lchip, p_stk_port->gport, &shp_profile), ret, unlock);
                    CTC_ERROR_GOTO(sys_usw_queue_set_port_drop_en(lchip, p_stk_port->gport, 1, &shp_profile), ret, unlock);
                    recover_quque = 1;
                    CTC_ERROR_GOTO(_sys_usw_stacking_check_port_status(lchip, p_stk_port->gport, &shp_profile), ret, unlock);
                    for (index = 0; index < tx_chan_num; index++)
                    {
                        CTC_ERROR_GOTO(_sys_usw_stacking_encap_header_disable(lchip, tx_chan_id[index], CTC_EGRESS), ret, unlock);
                    }
                    CTC_ERROR_GOTO(sys_usw_queue_set_port_drop_en(lchip, p_stk_port->gport, 0, &shp_profile), ret, unlock);
                    recover_quque = 0;
                    CTC_BMP_UNSET(g_stacking_master[lchip]->egr_port_en_bmp, CTC_MAP_GPORT_TO_LPORT(p_stk_port->gport));
                }

                if ((p_stk_port->direction == CTC_INGRESS) || (p_stk_port->direction == CTC_BOTH_DIRECTION))
                {
                    for (index = 0; index < rx_chan_num; index++)
                    {
                        CTC_ERROR_GOTO(_sys_usw_stacking_encap_header_disable(lchip, rx_chan_id[index], CTC_INGRESS), ret, unlock);
                    }
                    CTC_BMP_UNSET(g_stacking_master[lchip]->ing_port_en_bmp, CTC_MAP_GPORT_TO_LPORT(p_stk_port->gport));
                }
            }
        }
        break;
    case CTC_STK_PROP_LB_HASH_OFFSET:
        p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, p_lb_hash_offset->trunk_id);
        if (NULL == p_sys_trunk)
        {
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
            ret = CTC_E_NOT_EXIST;
            goto unlock;
        }
        cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_lb_hash_offset->trunk_id, cmd, &ds_link_aggregate_sgmac_group));
        if(CTC_LB_HASH_OFFSET_DISABLE != p_lb_hash_offset->value)
        {
            SetDsLinkAggregateChannelGroup(V, hashCfgPriorityIsHigher_f, &ds_link_aggregate_sgmac_group, 1);
            SetDsLinkAggregateChannelGroup(V, hashSelect_f, &ds_link_aggregate_sgmac_group, ((p_lb_hash_offset->value / 16)|0x8));
            SetDsLinkAggregateChannelGroup(V, hashOffset_f, &ds_link_aggregate_sgmac_group, p_lb_hash_offset->value % 16);
        }
        else
        {
            SetDsLinkAggregateChannelGroup(V, hashCfgPriorityIsHigher_f, &ds_link_aggregate_sgmac_group, 0);
        }
        cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_lb_hash_offset->trunk_id, cmd, &ds_link_aggregate_sgmac_group));
        break;
    default:
        ret = CTC_E_NOT_SUPPORT;
        goto unlock;
    }

    STACKING_UNLOCK;
    return CTC_E_NONE;

    unlock:
    if (recover_quque)
    {
        sys_usw_queue_set_port_drop_en(lchip, gport, 0, &shp_profile);
    }
    STACKING_UNLOCK;
    return ret;

}

int32
sys_usw_stacking_get_property(uint8 lchip, ctc_stacking_property_t* p_prop)
{
    int32 ret    = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    ctc_stacking_lb_hash_offset_t* p_lb_hash_offset = NULL;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_prop);
    if (CTC_STK_PROP_LB_HASH_OFFSET == p_prop->prop_type)
    {
        CTC_PTR_VALID_CHECK(p_prop->p_value);
        p_lb_hash_offset = (ctc_stacking_lb_hash_offset_t*)p_prop->p_value;
        SYS_STK_TRUNKID_RANGE_CHECK(p_lb_hash_offset->trunk_id);
    }

    STACKING_LOCK;

    switch (p_prop->prop_type)
    {

    case CTC_STK_PROP_GLOBAL_CONFIG:
        CTC_ERROR_GOTO(_sys_usw_stacking_get_global_cfg(lchip, (ctc_stacking_glb_cfg_t *)p_prop->p_value), ret, unlock);
        break;

    case CTC_STK_PROP_MCAST_STOP_RCHIP:
        CTC_ERROR_GOTO(_sys_usw_stacking_get_stop_rchip(lchip, (ctc_stacking_stop_rchip_t *)p_prop->p_value), ret, unlock);
        break;

    case CTC_STK_PROP_BREAK_EN:
        CTC_ERROR_GOTO(_sys_usw_stacking_get_break_en(lchip, &p_prop->value), ret, unlock);
        break;

    case CTC_STK_PROP_FULL_MESH_EN:
        CTC_ERROR_GOTO(_sys_usw_stacking_get_full_mesh_en(lchip, &p_prop->value), ret, unlock);
        break;

    case CTC_STK_PROP_PORT_BIND_TRUNK:
        {
            ctc_stacking_bind_trunk_t *p_bind_trunk = NULL;
            p_bind_trunk = (ctc_stacking_bind_trunk_t *)p_prop->p_value;

            if(!p_bind_trunk)
            {
                STACKING_UNLOCK;
                return CTC_E_INVALID_PTR;
            }
            CTC_ERROR_GOTO(sys_usw_stacking_get_binding_trunk(lchip, p_bind_trunk->gport, &p_bind_trunk->trunk_id), ret, unlock);
        }
        break;

    case CTC_STK_PROP_RCHIP_PORT_EN:
        CTC_ERROR_GOTO(_sys_usw_stacking_get_rchip_port(lchip, (ctc_stacking_rchip_port_t*)p_prop->p_value), ret, unlock);
        break;
    case CTC_STK_PROP_STK_PORT_EN:
        {
            ctc_stacking_port_cfg_t* p_stk_port;
            uint32 cmd = 0;
            uint32 field_val = 0;
            uint32 chan_id = 0;
            uint8 gchip = 0;
            p_stk_port = (ctc_stacking_port_cfg_t *)p_prop->p_value;
            if (p_stk_port->direction >= CTC_BOTH_DIRECTION)
            {
                ret = CTC_E_INVALID_PARAM;
                goto unlock;
            }
            gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_stk_port->gport);
            if (!sys_usw_chip_is_local(lchip, gchip))
            {
                ret = CTC_E_INVALID_CHIP_ID;
                goto unlock;
            }
            dmps_port_info.gport = p_stk_port->gport;
            CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id), ret, unlock);
            if (SYS_DMPS_INVALID_CHAN_ID == chan_id)
            {
                SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid localphy port \n");
    			ret =  CTC_E_INVALID_PORT;
                goto unlock;
            }

            if (p_stk_port->direction == CTC_INGRESS)
            {
                cmd = DRV_IOR(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_muxType_f);
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val), ret, unlock);
                p_stk_port->hdr_type = (field_val==DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2))?CTC_STK_HDR_WITH_L2:0;
                p_stk_port->enable = field_val?1:0;
            }
            else
            {
                EpeHdrAdjustChanCtl_m stacking_en;
                uint32 packet_header_en[SYS_STK_PORT_NUM_MAX/CTC_UINT32_BITS] = {0};
                uint16 chan_tmp = SYS_USW_CHANNEL_ENCODE(chan_id); /* for TMG, chan bit7 is dpid, bit6 is not use */

                cmd = DRV_IOR(EpeHdrAdjustChanCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &stacking_en), ret, unlock);
                GetEpeHdrAdjustChanCtl(A, packetHeaderEn_f, &stacking_en, packet_header_en);


                p_stk_port->enable = CTC_IS_BIT_SET(packet_header_en[chan_tmp>>5], (chan_tmp&0x1F))?1:0;
                cmd = DRV_IOR(DsPacketHeaderEditTunnel_t, DsPacketHeaderEditTunnel_packetHeaderL2En_f);
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val), ret, unlock);
                p_stk_port->hdr_type = field_val?CTC_STK_HDR_WITH_L2:0;
            }
        }
        break;
    case CTC_STK_PROP_LB_HASH_OFFSET:
        {
            uint32 lb_hash_offset = 0;
            uint32 cmd = 0;
            DsLinkAggregateChannelGroup_m ds_link_aggregate_sgmac_group;
            p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, p_lb_hash_offset->trunk_id);
            if (NULL == p_sys_trunk)
            {
                SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
                ret = CTC_E_NOT_EXIST;
                goto unlock;
            }
            cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_lb_hash_offset->trunk_id, cmd, &ds_link_aggregate_sgmac_group));
            if(GetDsLinkAggregateChannelGroup(V, hashCfgPriorityIsHigher_f, &ds_link_aggregate_sgmac_group))
            {
                lb_hash_offset = (GetDsLinkAggregateChannelGroup(V, hashSelect_f, &ds_link_aggregate_sgmac_group)&0x7)<<4;
                lb_hash_offset += GetDsLinkAggregateChannelGroup(V, hashOffset_f, &ds_link_aggregate_sgmac_group);
            }
            else
            {
                lb_hash_offset = CTC_LB_HASH_OFFSET_DISABLE;
            }
            p_lb_hash_offset->value = lb_hash_offset;
        }
        break;
    default:
        ret = CTC_E_NOT_SUPPORT;
        goto unlock;
    }

    STACKING_UNLOCK;
    return CTC_E_NONE;

    unlock:
    STACKING_UNLOCK;
	return ret;

}

int32
sys_usw_stacking_get_stkhdr_ver(uint8 lchip, uint8* p_legacy_en)
{
    *p_legacy_en = (g_stacking_master[lchip] && (g_stacking_master[lchip]->stacking_ver == CTC_STACKING_VERSION_1_0))?1:0;
    return CTC_E_NONE;
}

#define _____MCAST_TRUNK_GROUP_____ ""

int32
sys_usw_stacking_set_trunk_mcast_profile(uint8 lchip, ctc_stacking_trunk_mcast_profile_t* p_mcast_profile)
{
    int32 ret = CTC_E_NONE;
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;
    uint8 trunk_id = 0;
    uint16 index = 0;
    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_mcast_profile);

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "profile id: %d \n", p_mcast_profile->mcast_profile_id);

    if (p_mcast_profile->mcast_profile_id >= SYS_STK_MCAST_PROFILE_MAX)
    {
        return CTC_E_INVALID_PARAM;
    }
    for (trunk_id = 0; (p_mcast_profile->type == CTC_STK_MCAST_PROFILE_ADD) && trunk_id <= (CTC_CONST64-1); trunk_id++)
    {
        if (!CTC_IS_BIT_SET(p_mcast_profile->trunk_bitmap[trunk_id / 32], trunk_id % 32))
        {
            continue;
        }
        SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);
    }

    STACKING_LOCK;
    /*lookup*/
    sal_memset(&mcast_db, 0, sizeof(mcast_db));

    mcast_db.type = 0;
    mcast_db.id   = p_mcast_profile->mcast_profile_id;

    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);
    switch(p_mcast_profile->type)
    {
    case CTC_STK_MCAST_PROFILE_CREATE:
        {
            uint16 mcast_profile_id = 0;

            if (0 == p_mcast_profile->mcast_profile_id)
            {
                sys_usw_opf_t  opf;
                /*alloc profile id*/
                uint32 value_32 = 0;

                sal_memset(&opf, 0, sizeof(opf));
                opf.pool_type  = g_stacking_master[lchip]->opf_type;
                opf.pool_index = SYS_STK_OPF_MCAST_PROFILE;
                CTC_ERROR_GOTO(sys_usw_opf_alloc_offset(lchip, &opf, 1, &value_32),
                                                                       ret, Error);
                mcast_profile_id = value_32;

            }
            else
            {
                if (NULL != p_mcast_db)
                {
                    ret = CTC_E_ENTRY_EXIST;
                    goto Error;
                }

                mcast_profile_id = p_mcast_profile->mcast_profile_id;
            }

            ret = _sys_usw_stacking_mcast_group_create(lchip, 0,
                                                              mcast_profile_id,
                                                              &p_mcast_db,
                                                              p_mcast_profile->append_en);

            if (CTC_E_NONE != ret) /*roolback*/
            {
                if (0 == p_mcast_profile->mcast_profile_id)
                {
                    sys_usw_opf_t  opf;
                    sal_memset(&opf, 0, sizeof(opf));
                    opf.pool_type  = g_stacking_master[lchip]->opf_type;
                    opf.pool_index = SYS_STK_OPF_MCAST_PROFILE;
                    sys_usw_opf_free_offset(lchip, &opf, 1, mcast_profile_id);
                }
                goto Error;
            }

            if (0 == p_mcast_profile->mcast_profile_id)
            {
                if (NULL != p_mcast_db)
                {
                    p_mcast_db->alloc_id = 1;
                }

                p_mcast_profile->mcast_profile_id = mcast_profile_id;
            }
        }

        break;

    case CTC_STK_MCAST_PROFILE_DESTROY:
        {
            uint8 alloc_id;
            if (0 == p_mcast_profile->mcast_profile_id)
            {
                ret = CTC_E_NONE;
                goto Error;
            }

            if (NULL == p_mcast_db)
            {
                ret = CTC_E_NOT_EXIST;
                goto Error;
            }
            alloc_id = p_mcast_db->alloc_id;
            CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_destroy(lchip, 0,
                                                                       p_mcast_profile->mcast_profile_id, p_mcast_db),
                                                                       ret, Error);

            if (1 == alloc_id)
            {
                /*alloc profile id*/
                sys_usw_opf_t  opf;

                sal_memset(&opf, 0, sizeof(opf));
                opf.pool_type  = g_stacking_master[lchip]->opf_type;
                opf.pool_index = SYS_STK_OPF_MCAST_PROFILE;
                CTC_ERROR_GOTO(sys_usw_opf_free_offset(lchip, &opf, 1, p_mcast_profile->mcast_profile_id),
                                                                       ret, Error);
            }
        }

        break;

    case CTC_STK_MCAST_PROFILE_ADD:
        {
            uint32 bitmap[CTC_STK_TRUNK_BMP_NUM] = {0};
            uint8 trunk_id = 0;
            if (NULL == p_mcast_db)
            {
                ret = CTC_E_NOT_EXIST;
                goto Error;
            }
            for(index=0; index<SYS_STK_TRUNK_BMP_NUM; index++)
            {
                bitmap[index] = p_mcast_profile->trunk_bitmap[index] & (p_mcast_profile->trunk_bitmap[index] ^ p_mcast_db->trunk_bitmap[index]);
            }
            
            for (trunk_id = 1; trunk_id <= MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID); trunk_id++)
            {
                if (!CTC_IS_BIT_SET(bitmap[trunk_id / 32], trunk_id % 32))
                {
                    continue;
                }
                ret =  _sys_usw_stacking_mcast_group_add_member(lchip, p_mcast_db, trunk_id, 1);

                if (CTC_E_NONE != ret) /*roolback*/
                {
                    uint8 tmp_trunk_id = 0;

                    for (tmp_trunk_id = 1; tmp_trunk_id < trunk_id; tmp_trunk_id++)
                    {
                        if (!CTC_IS_BIT_SET(bitmap[tmp_trunk_id / 32], tmp_trunk_id % 32))
                        {
                            continue;
                        }
                        _sys_usw_stacking_mcast_group_remove_member(lchip, p_mcast_db, tmp_trunk_id, 1);
                    }

                    goto Error;
                }

            }
        }

        break;

    case CTC_STK_MCAST_PROFILE_REMOVE:
        {
            uint32 bitmap[CTC_STK_TRUNK_BMP_NUM] = {CTC_STK_TRUNK_BMP_NUM};
            uint8 trunk_id = 0;

            if (NULL == p_mcast_db)
            {
                ret = CTC_E_NOT_EXIST;
                goto Error;
            }

            for(index=0; index<SYS_STK_TRUNK_BMP_NUM; index++)
            {
                bitmap[index] = p_mcast_profile->trunk_bitmap[index] & p_mcast_db->trunk_bitmap[index];
            }

            for (trunk_id = 1; trunk_id <= MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID); trunk_id++)
            {
                if (!CTC_IS_BIT_SET(bitmap[trunk_id / 32], trunk_id % 32))
                {
                    continue;
                }
                ret = _sys_usw_stacking_mcast_group_remove_member(lchip, p_mcast_db, trunk_id, 1);

                if (CTC_E_NONE != ret)
                {
                    goto Error;
                }
            }
        }

        break;
    case CTC_STK_MCAST_PROFILE_ADD_WITH_NH:
        {
            CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_set_member_with_nh(lchip, p_mcast_db, p_mcast_profile->trunk_bitmap[0], 1), ret, Error);
        }
        break;
    case CTC_STK_MCAST_PROFILE_REMOVE_WITH_NH:
        {
            CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_set_member_with_nh(lchip, p_mcast_db, p_mcast_profile->trunk_bitmap[0], 0), ret, Error);
        }
        break;
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB, 1);
    STACKING_UNLOCK;
    return CTC_E_NONE;

    Error:
    STACKING_UNLOCK;
    return ret;
}


int32
sys_usw_stacking_get_trunk_mcast_profile(uint8 lchip, ctc_stacking_trunk_mcast_profile_t* p_mcast_profile)
{
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;
    uint16 index = 0;

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_mcast_profile);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "profile id: %d \n", p_mcast_profile->mcast_profile_id);

    if (p_mcast_profile->mcast_profile_id >= SYS_STK_MCAST_PROFILE_MAX)
    {
        return CTC_E_INVALID_PARAM;
    }

    /*lookup*/
    sal_memset(&mcast_db, 0, sizeof(mcast_db));

    mcast_db.type = 0;
    mcast_db.id   = p_mcast_profile->mcast_profile_id;

    STACKING_LOCK;
    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);

    if (NULL == p_mcast_db)
    {
        STACKING_UNLOCK;
        return CTC_E_NOT_EXIST;
    }

    for (index=0; index<SYS_STK_TRUNK_BMP_NUM; index++)
    {
        p_mcast_profile->trunk_bitmap[index] = p_mcast_db->trunk_bitmap[index];
    }

    STACKING_UNLOCK;
    return CTC_E_NONE;
}

int32
sys_usw_stacking_create_keeplive_group(uint8 lchip, uint16 group_id)
{
    int32 ret = CTC_E_NONE;
    uint32 group_size = 0;
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_STK_DBG_PARAM("create group:0x%x\n", group_id);

    SYS_STK_INIT_CHECK(lchip);

    CTC_ERROR_RETURN(sys_usw_ftm_get_dyn_entry_size(lchip, SYS_FTM_DYN_ENTRY_GLB_MET, &group_size));

    if (group_id >= group_size)
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(sys_usw_nh_check_glb_met_offset(lchip, group_id, 1, TRUE));
    CTC_ERROR_RETURN(sys_usw_nh_set_glb_met_offset(lchip, group_id, 1, TRUE));
    STACKING_LOCK;

    /*lookup*/
    sal_memset(&mcast_db, 0, sizeof(mcast_db));

    mcast_db.type = 1;
    mcast_db.id   = group_id;
    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);

    if (NULL != p_mcast_db)
    {
        ret =  CTC_E_ENTRY_EXIST;
        goto Error;
    }

    CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_create( lchip,  1, group_id, &p_mcast_db, 0),
                   ret, Error);

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB, 1);
    STACKING_UNLOCK;
    return CTC_E_NONE;

Error:
    STACKING_UNLOCK;
    sys_usw_nh_set_glb_met_offset(lchip, group_id, 1, FALSE);
    return ret;

}


int32
sys_usw_stacking_destroy_keeplive_group(uint8 lchip, uint16 group_id)
{
    int32 ret = CTC_E_NONE;
    uint32 group_size = 0;
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);

    SYS_STK_DBG_PARAM("destroy group:0x%x\n", group_id);

    CTC_ERROR_RETURN(sys_usw_ftm_get_dyn_entry_size(lchip, SYS_FTM_DYN_ENTRY_GLB_MET, &group_size));

    if (group_id >= group_size)
    {
        return CTC_E_INVALID_PARAM;
    }

    STACKING_LOCK;

    /*lookup*/
    sal_memset(&mcast_db, 0, sizeof(mcast_db));

    mcast_db.type = 1;
    mcast_db.id   = group_id;
    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);

    if (NULL == p_mcast_db)
    {
        ret =  CTC_E_NOT_EXIST;
        goto Error;
    }

    CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_destroy( lchip,  1, group_id, p_mcast_db),
                   ret, Error);

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB, 1);
    STACKING_UNLOCK;
    sys_usw_nh_set_glb_met_offset(lchip, group_id, 1, FALSE);
    return CTC_E_NONE;

Error:
    STACKING_UNLOCK;
    return ret;


}


int32
sys_usw_stacking_keeplive_add_member(uint8 lchip, ctc_stacking_keeplive_t* p_keeplive)
{
    int32 ret = CTC_E_NONE;
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_keeplive);


    SYS_STK_DBG_PARAM("trunk:0x%x, gport:0x%x, type:%d, group:0x%x\n",
                      p_keeplive->trunk_id, p_keeplive->cpu_gport, p_keeplive->mem_type, p_keeplive->group_id);


    if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_TRUNK)
    {
        SYS_STK_TRUNKID_RANGE_CHECK(p_keeplive->trunk_id);
    }

    STACKING_LOCK;

    /*lookup*/
    sal_memset(&mcast_db, 0, sizeof(mcast_db));

    mcast_db.type = 1;
    mcast_db.id   = p_keeplive->group_id;
    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);

    if (NULL == p_mcast_db)
    {
        ret =  CTC_E_NOT_EXIST;
        goto Error;
    }

    if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_TRUNK)
    {
        uint16 trunk_id = 0;

        trunk_id = p_keeplive->trunk_id;

        if (CTC_IS_BIT_SET(p_mcast_db->trunk_bitmap[trunk_id / 32], trunk_id % 32))
        {
            ret = CTC_E_MEMBER_EXIST;
            goto Error;
        }

        CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_add_member(lchip, p_mcast_db, trunk_id, 1),
                       ret, Error);
    }
    else if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_MCAST_PROFILE)
    {
        if (0 != p_mcast_db->mcast_prf_id)
        {
            ret = CTC_E_INVALID_PARAM;
            goto Error;
        }
        CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_set_member_with_nh(lchip, p_mcast_db, p_keeplive->trunk_bitmap[0], 1), ret, Error);
        p_mcast_db->mcast_prf_id = p_keeplive->trunk_bitmap[0];
    }
    else if (!CTC_IS_CPU_PORT(p_keeplive->cpu_gport))
    {
        uint16 dest_id = 0;
        if (FALSE == sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(p_keeplive->cpu_gport)))
        {
            ret = CTC_E_INVALID_PORT;
            goto Error;
        }
        dest_id = CTC_MAP_GPORT_TO_LPORT(p_keeplive->cpu_gport);
        CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_add_member(lchip, p_mcast_db, dest_id, 0),
                       ret, Error);
    }
    else
    {
        uint16 dest_id = 0;
        uint8 gchip_id = 0;
        uint16 sub_queue_id = 0;
        uint8 grp_id = 0;
        sys_nh_param_dsmet_t dsmet;

        sys_usw_get_gchip_id(lchip, &gchip_id);
        CTC_ERROR_GOTO(sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_C2C_PKT, &sub_queue_id), ret, Error);

        sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
        if (DRV_FROM_AT(lchip))
        {
            /* use exception_id replace next_hop_ptr */
            dsmet.next_hop_ptr_valid = 2;
            dsmet.next_hop_ptr = ((CTC_IS_BIT_SET(p_keeplive->cpu_gport, 0) ? MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT2) : MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT)));
        }
        else
        {
            dsmet.next_hop_ptr_valid = 1;
            dsmet.next_hop_ptr = CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_C2C_PKT, 0);
        }
        
        /*p_keeplive->cpu_gport(0) mean hign prio reason grp*/
        if (CTC_IS_BIT_SET(p_keeplive->cpu_gport, 0))
        {
            grp_id = (sub_queue_id / MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM)) + 1;
        }
        else
        {
            grp_id = (sub_queue_id / MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM));
        }

        /*to cpu based on prio*/
        dest_id =  SYS_ENCODE_EXCP_DESTMAP_MET_GRP(gchip_id, grp_id);
        dsmet.dest_id = dest_id;
        dsmet.dest_id_valid = 1;
        CTC_ERROR_GOTO(sys_usw_nh_update_dsmet(lchip, p_mcast_db->head_met_offset, &dsmet), ret, Error);
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB, 1);
Error:
    STACKING_UNLOCK;
    return ret;
}


int32
sys_usw_stacking_keeplive_remove_member(uint8 lchip, ctc_stacking_keeplive_t* p_keeplive)
{
    int32 ret = CTC_E_NONE;
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_keeplive);


    SYS_STK_DBG_PARAM("trunk:0x%x, gport:0x%x, type:%d, group:0x%x\n",
                      p_keeplive->trunk_id, p_keeplive->cpu_gport, p_keeplive->mem_type, p_keeplive->group_id);

    if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_TRUNK)
    {
        SYS_STK_TRUNKID_RANGE_CHECK(p_keeplive->trunk_id);
    }

    STACKING_LOCK;

    /*lookup*/
    sal_memset(&mcast_db, 0, sizeof(mcast_db));

    mcast_db.type = 1;
    mcast_db.id   = p_keeplive->group_id;
    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);

    if (NULL == p_mcast_db)
    {
        ret = CTC_E_NOT_EXIST;
        goto Error;
    }

    if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_TRUNK)
    {
        uint16 trunk_id = 0;

        trunk_id = p_keeplive->trunk_id;

        if (!CTC_IS_BIT_SET(p_mcast_db->trunk_bitmap[trunk_id / 32], trunk_id % 32))
        {
            ret =  CTC_E_MEMBER_NOT_EXIST;
            goto Error;
        }

        CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_remove_member(lchip, p_mcast_db, p_keeplive->trunk_id, 1),
                         ret, Error);
    }
    else if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_MCAST_PROFILE)
    {
        if (0 == p_mcast_db->mcast_prf_id)
        {
            ret = CTC_E_NOT_EXIST;
            goto Error;
        }
        CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_set_member_with_nh(lchip, p_mcast_db, p_keeplive->trunk_bitmap[0], 0), ret, Error);
        p_mcast_db->mcast_prf_id = 0;
    }
    else if (!CTC_IS_CPU_PORT(p_keeplive->cpu_gport))
    {
        uint16 dest_id = 0;
        if (FALSE == sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(p_keeplive->cpu_gport)))
        {
            ret = CTC_E_INVALID_PORT;
            goto Error;
        }
        dest_id = CTC_MAP_GPORT_TO_LPORT(p_keeplive->cpu_gport);
        CTC_ERROR_GOTO(_sys_usw_stacking_mcast_group_remove_member(lchip, p_mcast_db, dest_id, 0),
                       ret, Error);
    }
    else
    {
        sys_nh_param_dsmet_t dsmet;

        sal_memset(&dsmet, 0, sizeof(sys_nh_param_dsmet_t));
        if (DRV_FROM_AT(lchip))
        {
            /* use exception_id replace next_hop_ptr */
            dsmet.next_hop_ptr_valid = 2;
            dsmet.next_hop_ptr = ((CTC_IS_BIT_SET(p_keeplive->cpu_gport, 0) ? MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT2) : MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT)));
        }
        else
        {
            dsmet.next_hop_ptr_valid = 1;
            dsmet.next_hop_ptr = CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_C2C_PKT, 0);
        }

        dsmet.dest_id = SYS_RSV_PORT_DROP_ID;
        dsmet.dest_id_valid = 1;
        CTC_ERROR_GOTO(sys_usw_nh_update_dsmet(lchip, p_mcast_db->head_met_offset, &dsmet), ret, Error);
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB, 1);
Error:
    STACKING_UNLOCK;
    return ret;
}

int32
sys_usw_stacking_keeplive_get_members(uint8 lchip, ctc_stacking_keeplive_t* p_keeplive)
{
    int32 ret = CTC_E_NONE;
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_keeplive);

    SYS_STK_DBG_PARAM("group:0x%x mem_type:%d\n", p_keeplive->group_id, p_keeplive->mem_type);

    STACKING_LOCK;
    /*lookup*/
    sal_memset(&mcast_db, 0, sizeof(mcast_db));
    mcast_db.type = 1;
    mcast_db.id   = p_keeplive->group_id;
    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);
    if (NULL == p_mcast_db)
    {
        ret = CTC_E_NOT_EXIST;
        goto EXIT;
    }

    if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_TRUNK)
    {
        sal_memcpy(p_keeplive->trunk_bitmap, p_mcast_db->trunk_bitmap, sizeof(p_keeplive->trunk_bitmap));
        p_keeplive->trunk_bmp_en = 1;
    }
    else if (p_keeplive->mem_type == CTC_STK_KEEPLIVE_MEMBER_MCAST_PROFILE)
    {
        p_keeplive->trunk_bitmap[0] = p_mcast_db->mcast_prf_id;
    }
    else
    {
        uint16 dest_id                 = 0;
        uint32 dsnh_offset             = 0;
        uint8 gchip = 0;
        uint16 sub_queue_id = 0;
        uint32 met_offset = p_mcast_db->head_met_offset;
        sys_nh_param_dsmet_t dsmet;

        CTC_ERROR_GOTO(sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_C2C_PKT, &sub_queue_id), ret, EXIT);
        while (met_offset != 0xffff)
        {
            CTC_ERROR_GOTO(sys_usw_nh_get_dsmet(lchip, met_offset, &dsmet), ret, EXIT);
            met_offset = dsmet.next_met_entry_ptr;
            dsnh_offset = dsmet.next_hop_ptr;
            if (dsmet.remote_chip || (dsmet.dest_id == SYS_RSV_PORT_DROP_ID))
            {
                continue;
            }

            if ((dest_id != SYS_RSV_PORT_DROP_ID)
                && ((DRV_FROM_AT(lchip) && (dsnh_offset == MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT) || dsnh_offset == MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT2)))
                || ((!DRV_FROM_AT(lchip)) && (dsnh_offset == CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_C2C_PKT, 0)))))
            {
                sys_usw_get_gchip_id(lchip, &gchip);
                p_keeplive->cpu_gport = CTC_LPORT_CPU | ((gchip & CTC_GCHIP_MASK) << CTC_LOCAL_PORT_LENGTH);
                if ((dsmet.dest_id&0xF) != (sub_queue_id / MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM)))
                {
                    CTC_BIT_SET(p_keeplive->cpu_gport, 0);
                }
            }
            else if ((!DRV_FROM_AT(lchip) && (dsnh_offset != CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_C2C_PKT, 0)))
                || (DRV_FROM_AT(lchip) && (dsnh_offset != MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT)) && (dsnh_offset != MCHIP_CAP(SYS_CAP_CPU_REASON_EXCP_NONUC_C2C_PKT2))))
            {
                sys_usw_get_gchip_id(lchip, &gchip);
                p_keeplive->cpu_gport = dsmet.dest_id | ((gchip & CTC_GCHIP_MASK) << CTC_LOCAL_PORT_LENGTH);
            }
        }
    }

    EXIT:
    STACKING_UNLOCK;
    return ret;
}


int32
sys_usw_stacking_get_mcast_profile_met_offset(uint8 lchip,  uint16 mcast_profile_id, uint32 *p_stacking_met_offset)
{
    sys_stacking_mcast_db_t mcast_db;
    sys_stacking_mcast_db_t *p_mcast_db = NULL;

    CTC_PTR_VALID_CHECK(p_stacking_met_offset);

    if (NULL == g_stacking_master[lchip])
    {
        *p_stacking_met_offset = 0;
        return CTC_E_NONE;
    }

    if (0 == mcast_profile_id)
    {
        *p_stacking_met_offset = g_stacking_master[lchip]->bind_mcast_en?
        g_stacking_master[lchip]->stacking_mcast_offset : 0;
        return CTC_E_NONE;
    }


    STACKING_LOCK;

    sal_memset(&mcast_db, 0, sizeof(mcast_db));

    mcast_db.type = 0;
    mcast_db.id   = mcast_profile_id;
    p_mcast_db = ctc_hash_lookup(g_stacking_master[lchip]->mcast_hash, &mcast_db);


    if (NULL == p_mcast_db)
    {
        STACKING_UNLOCK;
        return CTC_E_NOT_EXIST;
    }

    *p_stacking_met_offset = p_mcast_db->head_met_offset;

    STACKING_UNLOCK;
    return CTC_E_NONE;
}






#define _____SYS_API_____ ""
int32
sys_usw_stacking_get_rsv_trunk_number(uint8 lchip, uint8* number)
{
    uint8 trunk_num = 0;
    uint8 trunk_idx = 0;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;

    CTC_PTR_VALID_CHECK(number);

    if (NULL == g_stacking_master[lchip])
    {
        *number = 0;
        return CTC_E_NONE;
    }

    STACKING_LOCK;
    for (trunk_idx = SYS_STK_TRUNK_MIN_ID; trunk_idx < MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID); trunk_idx++)
    {
        p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_idx);
        if (NULL != p_sys_trunk)
        {
            trunk_num++;
        }
    }
    STACKING_UNLOCK;

    if (trunk_num == 0)
    {
        *number = 0;
        return CTC_E_NONE;
    }

    if (trunk_num > 2)
    {
        *number = 8;
    }
    else
    {
        *number = 2;
    }

    return CTC_E_NONE;
}

int32
sys_usw_stacking_get_version(uint8 lchip, uint16 lport, uint8* version)
{
    uint32 chan_id = 0;
    uint8 gchip = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    sys_usw_get_gchip_id(lchip, &gchip);
    dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if ((SYS_DMPS_INVALID_CHAN_ID == chan_id) || (!SYS_IS_NETWORK_CHANNEL(chan_id)))
    {
        return CTC_E_INVALID_PORT;
    }

    CTC_ERROR_RETURN(_sys_usw_stacking_get_version(lchip, chan_id, version));

    return CTC_E_NONE;
}

int32
sys_usw_stacking_mcast_mode(uint8 lchip, uint8 mcast_mode)
{
    SYS_STK_INIT_CHECK(lchip);

    STACKING_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER, 1);
    g_stacking_master[lchip]->mcast_mode = mcast_mode;
    STACKING_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_stacking_src_port_mode(uint8 lchip, uint8 src_port_mode)
{
    uint32 cmd = 0;
    LagEngineCtl_m lag_engine_ctl;
    int32 ret = CTC_E_NONE;

    SYS_STK_INIT_CHECK(lchip);
    CTC_MAX_VALUE_CHECK(src_port_mode, SYS_STACKING_SRC_PORT_MODE_GCHIP);

    STACKING_LOCK;
    cmd = DRV_IOR(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl), ret, roll_back_0);
    SetLagEngineCtl(V, destChipSgMacSelMode_f, &lag_engine_ctl, (src_port_mode == SYS_STACKING_SRC_PORT_MODE_GCHIP)?1:0);
    cmd = DRV_IOW(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl), ret, roll_back_0);
    if (DRV_FROM_AT(lchip))
    {
        MetFifoCtl_m met_fifo_ctl;
        cmd = DRV_IOR(MetFifoCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &met_fifo_ctl), ret, roll_back_0);
        SetMetFifoCtl(V, destChipSgMacSelMode_f, &met_fifo_ctl, (src_port_mode == SYS_STACKING_SRC_PORT_MODE_GCHIP)? 1 : 0);
        cmd = DRV_IOW(MetFifoCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &met_fifo_ctl), ret, roll_back_0);
    }
    g_stacking_master[lchip]->src_port_mode = src_port_mode;

roll_back_0:
    STACKING_UNLOCK;
    return ret;
}

int32
sys_usw_stacking_update_load_mode(uint8 lchip, uint8 trunk_id, ctc_stacking_load_mode_t load_mode)
{
    SYS_STK_INIT_CHECK(lchip);
    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);
    CTC_MAX_VALUE_CHECK(load_mode, CTC_STK_LOAD_MODE_MAX-1);

    STACKING_LOCK;
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_stacking_update_load_mode(lchip, trunk_id, load_mode),
                                 g_stacking_master[lchip]->p_stacking_mutex);
    STACKING_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_stacking_trunk_set_rr_en(uint8 lchip, uint8 trunk_id, uint8 rr_en)
{
    int32 ret = CTC_E_NONE;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    uint32 cmd = 0;
    DsLinkAggregateChannelRrCount_m rr_count;
    DsLinkAggregateChannelGroup_m agg_grp;

    SYS_STK_INIT_CHECK(lchip);
    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);
    STACKING_LOCK;
    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        ret = CTC_E_NOT_EXIST;
        goto error_proc;
    }

    if ((trunk_id > CTC_CONST16) || (p_sys_trunk->mode != CTC_STK_LOAD_STATIC))
    {
        ret = CTC_E_INVALID_PARAM;
        goto error_proc;
    }

    /* 1. prepare DsLinkAggregateRrCount profile, profile id = trunk_id-1 */
    sal_memset(&rr_count, 0, sizeof(rr_count));
    cmd = DRV_IOW(DsLinkAggregateChannelRrCount_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, (trunk_id - 1), cmd, &rr_count), ret, error_proc);

    /* 2. modify trunk to rr mode and assign RrCount profile */
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, trunk_id, cmd, &agg_grp), ret, error_proc);
    SetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &agg_grp, rr_en?2:0);
    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, trunk_id, cmd, &agg_grp), ret, error_proc);

error_proc:
    STACKING_UNLOCK;
    return ret;
}

int32
sys_usw_stacking_get_trunk_by_rchip(uint8 lchip, uint8 remote_gchip, uint8* trunk_id)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint32 port_fwd_sel = 0;
    uint32 index = 0;
    uint32 entry_num_sgmac_map = 0;

    SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_STK_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(trunk_id);
    SYS_STK_CHIPID_CHECK(remote_gchip);

    CTC_ERROR_RETURN(sys_usw_ftm_query_table_entry_num(lchip, DsSgmacMap_t, &entry_num_sgmac_map));
    for (port_fwd_sel = 0; port_fwd_sel < (entry_num_sgmac_map/MCHIP_CAP(SYS_CAP_STK_MAX_GCHIP)); port_fwd_sel++)
    {
        index = (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)?(port_fwd_sel * MCHIP_CAP(SYS_CAP_STK_MAX_GCHIP)) + remote_gchip:(1 << 9) + remote_gchip;
        cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));
        if (field_val)
        {
            *trunk_id = field_val;
            break;
        }
    }

    return CTC_E_NONE;
}

#define _____DEBUG_SHOW_____ ""
STATIC int32
_sys_usw_stacking_show_trunk_path(uint8 lchip, uint8 trunk_id)
{
    uint32 port_fwd_sel            = 0;
    uint16 rchip                   = 0;
    uint16 lport                   = 0;
    uint32 cmd                     = 0;
    uint32 index                   = 0;
    uint32 field_val               = 0;
    uint8  i = 0;
    uint32 port_type = 0;
    uint8 gchip = 0;
    uint8 bpe_en = 0;
    uint32* p_bmp = NULL;
    uint32* p_tmp_bmp = NULL;
    int32 ret = CTC_E_NONE;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STK_DBG_DUMP("\ntrunk select path \n");
    SYS_STK_DBG_DUMP("%-10s %-10s %10s\n", "pbm", "rchip", "hash");
    SYS_STK_DBG_DUMP("======================================\n");
    sys_usw_get_gchip_id(lchip, &gchip);
    CTC_ERROR_RETURN(sys_usw_nh_get_bpe_en(lchip, &bpe_en));
    p_bmp = (uint32*)mem_malloc(MEM_STK_MODULE, SYS_STK_MAX_GCHIP*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/CTC_UINT32_BITS*sizeof(uint32));
    if (!p_bmp)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_bmp, 0, SYS_STK_MAX_GCHIP*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/CTC_UINT32_BITS*sizeof(uint32));


    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_STK_MAX_LPORT); lport++)
    {
        dmps_port_info.gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, lport);
        CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE,
        (void *)&port_type), ret,done);

        if (SYS_DMPS_NETWORK_PORT != port_type && !bpe_en && (SYS_DMPS_CPUMAC_NETWORK_PORT != port_type))
        {
            continue;
        }

        cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexFwdSgGroupSel_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_fwd_sel), ret,done);

        for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
        {
            p_tmp_bmp = (uint32*)p_bmp+rchip*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/CTC_UINT32_BITS;
            index = (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)?(port_fwd_sel << 7) + rchip:(1 << 9) + rchip;
            cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val), ret,done);
            if (trunk_id != field_val)
            {
                continue;
            }
            CTC_BMP_SET(p_tmp_bmp, lport);
        }
    }

    for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
    {
        p_tmp_bmp = (uint32*)p_bmp + rchip*MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/CTC_UINT32_BITS;
        for (i = 0; i < (MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)/CTC_UINT32_BITS); i++)
        {
            if (!p_tmp_bmp[i])
            {
                continue;
            }

            if (i == 0)
            {
                SYS_STK_DBG_DUMP("0x%08x %-10d %10s\n", p_tmp_bmp[i],  rchip, "-");
            }
            else
            {
                SYS_STK_DBG_DUMP("0x%08x\n", p_tmp_bmp[i]);
            }
            SYS_STK_DBG_DUMP("\n");
        }
    }

    if(SYS_STACKING_SRC_PORT_MODE_HASH == g_stacking_master[lchip]->src_port_mode)
    {
        for (index = 0; index < CTC_CONST256; index++)
        {
            cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val), ret,done);
            if (trunk_id != field_val)
            {
                continue;
            }
            SYS_STK_DBG_DUMP("%-10s %-10s %10u\n", "-",  "-", index);
        }
    }

done:
    mem_free(p_bmp);
    return ret;
}

int32
sys_usw_stacking_show_trunk_info(uint8 lchip, uint8 trunk_id)
{
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    uint32 mem_idx                 = 0;
    uint32 cmd                     = 0;
    uint8 load_mode                = 0;
    uint16 mem_base                = 0;
    uint16 mem_cnt                 = 0;
    uint32 field_val               = 0;
    uint32 gport                   = 0;
    uint8 gchip_id                 = 0;
    uint8 trunk_mode               = 0;
    char* mode[4] = {"Static", "Dynamic", "Failover", "Reserved"};
    DsLinkAggregateChannelGroup_m ds_link_aggregate_sgmac_group;
    DsLinkAggregateChannelMember_m ds_link_aggregate_sgmac_member;

    SYS_STK_INIT_CHECK(lchip);
    SYS_STK_TRUNKID_RANGE_CHECK(trunk_id);

    STACKING_LOCK;
    p_sys_trunk = ctc_vector_get(g_stacking_master[lchip]->p_trunk_vec, trunk_id);
    if (NULL == p_sys_trunk)
    {
        SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [STACKING] Trunk not exist \n");
        STACKING_UNLOCK;
        return CTC_E_NOT_EXIST;
    }
    trunk_mode = (p_sys_trunk->mode>=CTC_STK_LOAD_MODE_MAX)?CTC_STK_LOAD_MODE_MAX:p_sys_trunk->mode;
    STACKING_UNLOCK;

    sal_memset(&ds_link_aggregate_sgmac_group, 0, sizeof(DsLinkAggregateChannelGroup_m));
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, trunk_id, cmd, &ds_link_aggregate_sgmac_group));

    load_mode = GetDsLinkAggregateChannelGroup(V, channelLinkAggLbMode_f, &ds_link_aggregate_sgmac_group);
    mem_cnt = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_link_aggregate_sgmac_group);
    mem_base    = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_link_aggregate_sgmac_group);

    SYS_STK_DBG_DUMP("stacking trunk info below:\n");

    SYS_STK_DBG_DUMP("--------------------------------\n");
    SYS_STK_DBG_DUMP("trunk member ports\n");
    SYS_STK_DBG_DUMP("--------------------------------\n");
    SYS_STK_DBG_DUMP("trunk id:%d, mode:%s, count:%d\n", trunk_id, mode[trunk_mode],mem_cnt);
    sal_memset(&ds_link_aggregate_sgmac_member, 0, sizeof(ds_link_aggregate_sgmac_member));

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
    if (load_mode != 1)
    {
        cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
        for (mem_idx = 0; mem_idx < mem_cnt; mem_idx++)
        {
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mem_base+mem_idx, cmd, &field_val));
            gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, SYS_USW_CHANNEL_DECODE(field_val)));
            SYS_STK_DBG_DUMP("Member port:0x%x\n", gport);
        }
    }
    else
    {
        uint16 step = 0;
        step = DsLinkAggregateChannelMemberSet_array_1_channelId_f - DsLinkAggregateChannelMemberSet_array_0_channelId_f;

        for (mem_idx = 0; mem_idx < mem_cnt; mem_idx++)
        {
            cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DsLinkAggregateChannelMemberSet_array_0_channelId_f + mem_idx*step);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, trunk_id, cmd, &field_val));
            gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, SYS_USW_CHANNEL_DECODE(field_val)));
            SYS_STK_DBG_DUMP("Member port:0x%x\n", gport);
        }
    }

    _sys_usw_stacking_show_trunk_path(lchip, trunk_id);
    return CTC_E_NONE;
}

int32
sys_usw_stacking_show_status(uint8 lchip)
{
    SYS_STK_INIT_CHECK(lchip);

    STACKING_LOCK;
    SYS_STK_DBG_DUMP("Global configure:\n");
    SYS_STK_DBG_DUMP("--------------------------------------------------------------------\n");
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Fabric mode",          g_stacking_master[lchip]->fabric_mode);
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Trunk mcast mode",     g_stacking_master[lchip]->mcast_mode);
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Trunk member mode",    g_stacking_master[lchip]->trunk_mode);
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Default mcast offset", g_stacking_master[lchip]->stacking_mcast_offset);
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Header version",       g_stacking_master[lchip]->stacking_ver);
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Source port mode",     g_stacking_master[lchip]->src_port_mode);

    if (!g_stacking_master[lchip]->src_port_mode)
    {
        SYS_STK_DBG_DUMP("\nTrunk path select profile:\n");
        SYS_STK_DBG_DUMP("--------------------------------------------------------------------\n");
        SYS_STK_DBG_DUMP("%-30s :%10d\n", "Total profile count",  g_stacking_master[lchip]->p_fwd_prof_spool->max_count);
        SYS_STK_DBG_DUMP("%-30s :%10d\n", "Used count",           g_stacking_master[lchip]->p_fwd_prof_spool->count);
    }

    SYS_STK_DBG_DUMP("\nTrunk port block profile:\n");
    SYS_STK_DBG_DUMP("--------------------------------------------------------------------\n");
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Total profile count",  g_stacking_master[lchip]->p_block_prof_spool->max_count);
    SYS_STK_DBG_DUMP("%-30s :%10d\n", "Used count",           g_stacking_master[lchip]->p_block_prof_spool->count);
    STACKING_UNLOCK;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_travel_cb(void* array_data, void* user_data)
{
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    uint32  lchip = 0;
    uint8  rchip = 0;
    uint16 lport = 0;
    uint32 cmd = 0;
    uint32 port_fwd_sel = 0;
    uint32 field_val = 0;
    uint16 index = 0;
	uint32 bmp[SYS_STK_MAX_GCHIP/CTC_UINT32_BITS] = {0};
    char* load_mode_str[CTC_STK_LOAD_MODE_MAX] = {"Static", "Dynamic", "Failover"};
    DsLinkAggregateChannelGroup_m chan_grp;
    uint32 lb_offset = 0;
    char str[CTC_CONST32] = {0};
    uint8 mem_num = 0;
    uint8 gchip = 0;
    uint32 port_type = 0;
    uint8  bpe_en = 0;
    uint8  lb_offset_en = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    lchip  = *((uint8*)user_data);
    p_sys_trunk = (sys_stacking_trunk_info_t*)array_data;
    sys_usw_get_gchip_id(lchip, &gchip);
    CTC_ERROR_RETURN(sys_usw_nh_get_bpe_en(lchip, &bpe_en));

    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM); lport++)
    {
        dmps_port_info.gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, lport);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE,
            (void *)&port_type));

        if (SYS_DMPS_NETWORK_PORT != port_type && !bpe_en && (SYS_DMPS_CPUMAC_NETWORK_PORT != port_type))
        {
            continue;
        }

        cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexFwdSgGroupSel_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_fwd_sel));

        for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
        {
            index = (SYS_STACKING_SRC_PORT_MODE_HASH != g_stacking_master[lchip]->src_port_mode)?(port_fwd_sel<<7) + rchip:(1 << 9) + rchip;
			cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));

            if (p_sys_trunk->trunk_id == field_val)
            {
                CTC_BMP_SET(bmp, rchip);
            }
        }
    }

    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_sys_trunk->trunk_id, cmd, &chan_grp));
    if (GetDsLinkAggregateChannelGroup(V, hashCfgPriorityIsHigher_f, &chan_grp))
    {
        lb_offset_en = 1;
        lb_offset = (GetDsLinkAggregateChannelGroup(V, hashSelect_f, &chan_grp)&0x7)*16;
        lb_offset += GetDsLinkAggregateChannelGroup(V, hashOffset_f, &chan_grp);
        sal_sprintf(str, "%u", lb_offset);
    }
    else
    {
        sal_sprintf(str, "%s", "-");
    }
    mem_num = GetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &chan_grp);
    SYS_STK_DBG_DUMP("%-10u%-10s%-2u: 0x%08x%16s0x%-15x%-16s%-16u\n", p_sys_trunk->trunk_id, load_mode_str[p_sys_trunk->mode],
        0, bmp[0], "", p_sys_trunk->flag, str, mem_num);
    if (bmp[1])
    {
        SYS_STK_DBG_DUMP("%-20s%-2u: 0x%08x%20s\n", "", 32, bmp[1], "");
    }
    if (bmp[2])
    {
        SYS_STK_DBG_DUMP("%-20s%-2u: 0x%08x%20s\n","",64, bmp[2], "");
    }
    if (bmp[3])
    {
        SYS_STK_DBG_DUMP("%-20s%-2u: 0x%08x%20s\n","", 96, bmp[3], "");
    }
    if(lb_offset_en)
    {
        SYS_STK_DBG_DUMP("select group id(4 select group):%d\n",lb_offset/32);
        SYS_STK_DBG_DUMP("select group id(8 select group):%d\n",lb_offset/16);
    }
    return CTC_E_NONE;
}

int32
sys_usw_stacking_show_trunk_brief(uint8 lchip)
{
    SYS_STK_INIT_CHECK(lchip);

    STACKING_LOCK;
    SYS_STK_DBG_DUMP("\n%-10s%-10s%-30s%-15s%-15s%-15s\n", "Trunk-ID", "Load-Mode", "Rchip(Base:Offset bitmap)", "Flag", "LB-Offset", "Mem-Num");
    SYS_STK_DBG_DUMP("-----------------------------------------------------------------------------------------\n");

    ctc_vector_traverse(g_stacking_master[lchip]->p_trunk_vec, (vector_traversal_fn)_sys_usw_stacking_travel_cb, (void*)&lchip);
    STACKING_UNLOCK;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_stacking_traverse_fprintf_pool(void* node, sys_dump_db_traverse_param_t* user_date)
{
    uint8 lchip = user_date->lchip;
    sal_file_t                  p_file      = (sal_file_t)user_date->value0;
    uint32*                     cnt         = (uint32 *)(user_date->value1);
    uint32 j = 0;
    uint32 type = *((uint32 *)(user_date->value2));
    uint8  tmp_port_group;
    uint8  k;
    uint16 index = 0;
    uint32 bitmap[SYS_STK_MAX_LPORT_IN_WORD] = {0};
    uint32 cmd = 0;
    uint32 field_val = 0;

    if (type == 0)
    {
        sys_stacking_block_profile_t*   p_block_db =  NULL;
        p_block_db = (sys_stacking_block_profile_t*)((ctc_spool_node_t*)node)->data;
        if(((ctc_spool_node_t*)node)->ref_cnt == 0xFFFFFFFF)
        {
            SYS_DUMP_DB_LOG(p_file, "%-10s:%-5ustatic\n","Node", *cnt);
        }
        else
        {
            SYS_DUMP_DB_LOG(p_file, "%-10s:%-5u,     %-10s:%-5u\n","Node", *cnt, "refcnt", ((ctc_spool_node_t*)node)->ref_cnt);
        }
        SYS_DUMP_DB_LOG(p_file, "%-10s\n","----------------------------------------");
        SYS_DUMP_DB_LOG(p_file, "%-20s:%u\n","profile_id", p_block_db->profile_id);

        tmp_port_group = (g_stacking_master[lchip]->max_block_port_id+ 64)>>6;

        sal_memset(&bitmap, 0, sizeof(bitmap));

        cmd = DRV_FROM_AT(lchip)? DRV_IOR(DsMcQWriteCFlexDstChannelBlockMask_t, DsMcQWriteCFlexDstChannelBlockMask_dstPortBitMap_f):
        DRV_IOR(DsCFlexDstChannelBlockMask_t, DsCFlexDstChannelBlockMask_dstPortBitMap_f);
        for (j = 0; j <= g_stacking_master[lchip]->max_gchip_id; j++)
        {
            SYS_DUMP_DB_LOG(p_file, "[");
            for(k=0; k < tmp_port_group-1; k++)
            {
                SYS_USW_STK_ENCODE_BLOCK_INDEX(lchip,j, p_block_db->profile_id, k, index);
                DRV_FIELD_IOCTL(lchip, index, cmd, &bitmap[k<<1]);
                SYS_DUMP_DB_LOG(p_file, "%08x,", bitmap[k<<1]);
                SYS_DUMP_DB_LOG(p_file, "%08x,", bitmap[(k<<1)+1]);
            }
            SYS_USW_STK_ENCODE_BLOCK_INDEX(lchip,j, p_block_db->profile_id, k, index);
            DRV_FIELD_IOCTL(lchip, index, cmd, &bitmap[k<<1]);
            SYS_DUMP_DB_LOG(p_file, "%08x,", bitmap[k<<1]);
            SYS_DUMP_DB_LOG(p_file, "%08x] ", bitmap[(k<<1)+1]);

            if ((j+1) % (8/tmp_port_group) == 0)
            {
                SYS_DUMP_DB_LOG(p_file, "\n");
            }
        }
    }
    else
    {
        sys_stacking_fwd_profile_t*   p_fwd_db =  NULL;

        p_fwd_db = (sys_stacking_fwd_profile_t*)((ctc_spool_node_t*)node)->data;
        if(((ctc_spool_node_t*)node)->ref_cnt == 0xFFFFFFFF)
        {
            SYS_DUMP_DB_LOG(p_file, "%-10s:%-5ustatic\n","Node", *cnt);
        }
        else
        {
            SYS_DUMP_DB_LOG(p_file, "%-10s:%-5u,     %-10s:%-5u\n","Node", *cnt, "refcnt", ((ctc_spool_node_t*)node)->ref_cnt);
        }
        SYS_DUMP_DB_LOG(p_file, "%-10s\n","----------------------------------------");
        SYS_DUMP_DB_LOG(p_file, "%-20s:%u\n","profile_id", p_fwd_db->profile_id);
        for (j = 0; j < SYS_STK_MAX_GCHIP; j++)
        {
            index = (p_fwd_db->profile_id << 7) + j;
            cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));
            SYS_DUMP_DB_LOG(p_file, "[%02u] ", field_val);
            if (((j+1)%16) == 0)
            {
                SYS_DUMP_DB_LOG(p_file, "\n");
            }
        }
    }

    return 0;
}

int32
sys_usw_stacking_dump_db(uint8 lchip, sal_file_t p_f, ctc_global_dump_db_t* p_dump_param)
{
    int32 ret = CTC_E_NONE;
    uint32 i = 0;
    uint32 j = 0;
    sys_dump_db_traverse_param_t    cb_data;
    uint32 num_cnt = 0;
    uint32 spool_type = 0;
    uint16 lport = 0;
    uint8  gchip = 0;

    SYS_STK_INIT_CHECK(lchip);
    STACKING_LOCK;

    sys_usw_get_gchip_id(lchip, &gchip);

    SYS_DUMP_DB_LOG(p_f, "\n");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "# Stacking");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","fabric_mode",          g_stacking_master[lchip]->fabric_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","trunk_mode",           g_stacking_master[lchip]->trunk_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","stacking_mcast_offset",g_stacking_master[lchip]->stacking_mcast_offset);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","mcast_mode",           g_stacking_master[lchip]->mcast_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","binding_trunk",        g_stacking_master[lchip]->binding_trunk);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","bind_mcast_en",        g_stacking_master[lchip]->bind_mcast_en);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","src_port_mode",        g_stacking_master[lchip]->src_port_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","cflex isolation mode", g_stacking_master[lchip]->isolation_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max gchip id",         g_stacking_master[lchip]->max_gchip_id);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max block port id",    g_stacking_master[lchip]->max_block_port_id);

    SYS_DUMP_DB_LOG(p_f, "%-35s\n","Ingress port enable");
    SYS_DUMP_DB_LOG(p_f, "%-35s\n","Gport:");
    for (i = 0; i < sizeof(ctc_port_bitmap_t) / sizeof(uint32); i++)
    {
        for (j = 0; j < CTC_UINT32_BITS; j++)
        {
            lport = i * CTC_UINT32_BITS + j;
            if (CTC_BMP_ISSET(g_stacking_master[lchip]->ing_port_en_bmp, lport))
            {
                SYS_DUMP_DB_LOG(p_f, "    [0x%.4x] ", CTC_MAP_LPORT_TO_GPORT(gchip, lport));
            }
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s\n","Egress port enable");
    SYS_DUMP_DB_LOG(p_f, "%-35s\n","Gport:");
    for (i = 0; i < sizeof(ctc_port_bitmap_t) / sizeof(uint32); i++)
    {
        for (j = 0; j < CTC_UINT32_BITS; j++)
        {
            lport = i * CTC_UINT32_BITS + j;
            if (CTC_BMP_ISSET(g_stacking_master[lchip]->egr_port_en_bmp, lport))
            {
                SYS_DUMP_DB_LOG(p_f, "    [0x%.4x] ", CTC_MAP_LPORT_TO_GPORT(gchip, lport));
            }
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");
    sys_usw_opf_fprint_alloc_used_info(lchip, g_stacking_master[lchip]->opf_type, p_f);

    sal_memset(&cb_data, 0, sizeof(sys_dump_db_traverse_param_t));
    cb_data.lchip = lchip;
    cb_data.value0 = p_f;
    cb_data.value1 = &num_cnt;
    cb_data.value2 = &spool_type;
    SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","p_block_prof_spool(index:gchip id, data:port bitmap)");
    ctc_spool_traverse(g_stacking_master[lchip]->p_block_prof_spool, (spool_traversal_fn)_sys_usw_stacking_traverse_fprintf_pool , (void*)(&cb_data));

    sal_memset(&cb_data, 0, sizeof(sys_dump_db_traverse_param_t));
    num_cnt = 0;
    spool_type = 1;
    cb_data.lchip = lchip;
    cb_data.value0 = p_f;
    cb_data.value1 = &num_cnt;
    cb_data.value2 = &spool_type;
    SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","p_fwd_prof_spool(index:gchip id, data:trunk id)");
    ctc_spool_traverse(g_stacking_master[lchip]->p_fwd_prof_spool, (spool_traversal_fn)_sys_usw_stacking_traverse_fprintf_pool , (void*)(&cb_data));
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");
    STACKING_UNLOCK;

    return ret;
}

#define _____WARM_BOOT_____ ""


STATIC int32
_sys_usw_stacking_wb_restore_block_profile(uint8 lchip)
{
    int32 ret                      = 0;
    uint32 cmd                     = 0;
    uint32 port_block_sel          = 0;
    uint16 lport                   = 0;
    uint16 index                   = 0;
    sys_stacking_block_profile_t* p_profile_get = NULL;
    sys_stacking_block_profile_t* p_new_profile = NULL;
    uint8 rchip                    = 0;
    uint8 loop                     = 0;
    uint8 loop_max = (g_stacking_master[lchip]->max_block_port_id+64) >> 6;

    p_new_profile = (sys_stacking_block_profile_t*)mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_block_profile_t));
    if (NULL == p_new_profile)
    {
        return CTC_E_NO_MEMORY;
    }
    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_STK_MAX_LPORT); lport++)
    {
        cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexDstIsolateGroupSel_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_block_sel), ret, out);

        if (0 == port_block_sel)
        {
            continue;
        }

        sal_memset(p_new_profile, 0, sizeof(sys_stacking_block_profile_t));

        p_new_profile->profile_id = port_block_sel;
        p_new_profile->lchip = lchip;
        cmd = DRV_FROM_AT(lchip)? DRV_IOR(DsMcQWriteCFlexDstChannelBlockMask_t, DsMcQWriteCFlexDstChannelBlockMask_dstPortBitMap_f):
        DRV_IOR(DsCFlexDstChannelBlockMask_t, DsCFlexDstChannelBlockMask_dstPortBitMap_f);
        for (rchip = 0; rchip <= g_stacking_master[lchip]->max_gchip_id; rchip++)
        {
            /*In hw table, one entry store 64 ports bitmap*/
            for(loop=0; loop < loop_max; loop++)
            {
                SYS_USW_STK_ENCODE_BLOCK_INDEX(lchip,rchip, port_block_sel, loop, index);
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &p_new_profile->bitmap[rchip][loop<<1]), ret, out);
            }
        }

        CTC_ERROR_GOTO(ctc_spool_add(g_stacking_master[lchip]->p_block_prof_spool,
                                       p_new_profile,
                                       NULL,
                                       &p_profile_get), ret, out);


        g_stacking_master[lchip]->p_block_profile[port_block_sel] = p_profile_get;

    }

out:
    if (p_new_profile)
    {
        mem_free(p_new_profile);
    }

    return ret;

}

STATIC int32
_sys_usw_stacking_wb_restore_fwd_profile(uint8 lchip)
{
    int32 ret                      = 0;
    uint32 cmd                     = 0;
    uint16 lport                   = 0;
    uint32 port_fwd_sel            = 0;
    uint8 rchip                    = 0;
    uint16 index                   = 0;
    uint32 field_val               = 0;
    sys_stacking_fwd_profile_t* p_profile_get = NULL;
    sys_stacking_fwd_profile_t new_profile;


    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_STK_MAX_LPORT); lport++)
    {
        cmd = DRV_IOR(DsSrcPort_t, DsSrcPort_cFlexFwdSgGroupSel_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &port_fwd_sel));
        if (0 == port_fwd_sel)
        {
            continue;
        }

        sal_memset(&new_profile, 0, sizeof(new_profile));

        new_profile.lchip = lchip;
        new_profile.profile_id = port_fwd_sel;

        for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
        {
            index = (port_fwd_sel << 7) + rchip;
            cmd = DRV_IOR(DsSgmacMap_t, DsSgmacMap_linkAggregationChannelGroup_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &field_val));
			new_profile.trunk[rchip] = field_val;
        }

        CTC_ERROR_RETURN(ctc_spool_add(g_stacking_master[lchip]->p_fwd_prof_spool,
                                       &new_profile,
                                       NULL,
                                       &p_profile_get));


        g_stacking_master[lchip]->p_fwd_profile[port_fwd_sel] = p_profile_get;

    }



    return ret;

}


STATIC int32
_sys_usw_stacking_wb_restore_glb_port(uint8 lchip)
{
    int32 ret                      = 0;
    uint32 cmd                     = 0;
    uint16 max                     = 0;
    uint16 min                     = 0;
    uint32 base                    = 0;
	uint8  rchip                   = 0;
	sys_usw_opf_t  opf;
	DsGlbDestPortMap_m port_map;
    uint8 gchip_id;

    for (rchip = 0; rchip < SYS_STK_MAX_GCHIP; rchip++)
    {
        sys_usw_get_gchip_id(lchip, &gchip_id);
        if(rchip == gchip_id)
        {
            continue;
        }

        cmd = DRV_IOR(DsGlbDestPortMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, rchip, cmd, &port_map));

        base   = GetDsGlbDestPortMap(V, glbDestPortBase_f, &port_map);
        max    = GetDsGlbDestPortMap(V, glbDestPortMax_f, &port_map);
        min    = GetDsGlbDestPortMap(V, glbDestPortMin_f, &port_map);

        if (min == 1 && max == 0)
        {
            continue;
        }

        sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
        opf.pool_type  = g_stacking_master[lchip]->opf_type;
        opf.pool_index = SYS_STK_OPF_ABILITY;
        CTC_ERROR_RETURN(sys_usw_opf_alloc_offset_from_position(lchip, &opf, max + 1, base));

    }

    return ret;
}


int32
_sys_usw_stacking_wb_traverse_sync_trunk_node(void *data,uint32 vec_index, void *user_data)
{
    int32 ret = 0;
    uint16 mem_cnt = 0;
    uint16 mem_base = 0;
    uint8 is_dlb = 0;
    sys_stacking_trunk_info_t *p_sys_trunk = (sys_stacking_trunk_info_t*)data;
    ctc_wb_data_t *wb_data = (ctc_wb_data_t*)user_data;
    sys_wb_stacking_trunk_t   *p_wb_trunk_node = NULL;
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb_trunk_node = (sys_wb_stacking_trunk_t *)wb_data->buffer + wb_data->valid_cnt;

    p_wb_trunk_node->trunk_id = vec_index;
    p_wb_trunk_node->max_mem_cnt = p_sys_trunk->max_mem_cnt;
    p_wb_trunk_node->flow_cnt = p_sys_trunk->flow_cnt;
    p_wb_trunk_node->replace_en = p_sys_trunk->replace_en;
    p_wb_trunk_node->mode = p_sys_trunk->mode;
    p_wb_trunk_node->rsv1 = 0;
    if (p_sys_trunk->p_encap_hdr)
    {
        CTC_ERROR_RETURN(_sys_usw_stacking_get_trunk_info(((wb_data->app_id>>16) & 0xFF), vec_index, &mem_cnt, &mem_base, &is_dlb));
        if (0 == mem_cnt)
        {
#ifndef CTC_SHELL_DEBUG_ON
            SYS_STK_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[STACKING] Trunk no member port, error to sync encap header, and cannot restore\n");
#endif
        }
    }
    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

extern int32
sys_usw_nh_offset_alloc_from_position(uint8 lchip, sys_nh_entry_table_type_t entry_type,
                                            uint32 entry_num, uint32 start_offset);

int32
_sys_usw_stacking_wb_mapping_mcast(uint8 lchip, sys_wb_stacking_mcast_db_t *p_wb_mcast_info, sys_stacking_mcast_db_t *p_mcast_info, uint8 sync)
{

    if (sync)
    {
        p_wb_mcast_info->type = p_mcast_info->type;
        p_wb_mcast_info->id = p_mcast_info->id;
        p_wb_mcast_info->head_met_offset = p_mcast_info->head_met_offset;
        p_wb_mcast_info->tail_met_offset = p_mcast_info->tail_met_offset;
        p_wb_mcast_info->append_en = p_mcast_info->append_en;
        p_wb_mcast_info->alloc_id = p_mcast_info->alloc_id;
        p_wb_mcast_info->last_tail_offset = p_mcast_info->last_tail_offset;
        p_wb_mcast_info->mcast_prf_id = p_mcast_info->mcast_prf_id;
        sal_memcpy(p_wb_mcast_info->trunk_bitmap, p_mcast_info->trunk_bitmap, sizeof(uint32)*CTC_STK_TRUNK_BMP_NUM);
        p_wb_mcast_info->rsv1 = 0;
    }
    else
    {

        p_mcast_info->type = p_wb_mcast_info->type;
        p_mcast_info->id = p_wb_mcast_info->id;
        p_mcast_info->head_met_offset = p_wb_mcast_info->head_met_offset;
        p_mcast_info->tail_met_offset = p_wb_mcast_info->tail_met_offset;
        p_mcast_info->append_en = p_wb_mcast_info->append_en;
        p_mcast_info->alloc_id = p_wb_mcast_info->alloc_id;
        p_mcast_info->last_tail_offset = p_wb_mcast_info->last_tail_offset;
        p_mcast_info->mcast_prf_id = p_wb_mcast_info->mcast_prf_id;
        sal_memcpy(p_mcast_info->trunk_bitmap, p_wb_mcast_info->trunk_bitmap, sizeof(uint32)*SYS_WB_STK_TRUNK_BMP_NUM);
    }

    return CTC_E_NONE;
}


int32
_sys_usw_stacking_wb_sync_mcast_func(sys_stacking_mcast_db_t *p_mcast_info, void *user_data)
{
    uint32 max_entry_cnt = 0;
    sys_wb_stacking_mcast_db_t  *p_wb_mcast_info;
    sys_traverse_t *data = (sys_traverse_t *)user_data;
    ctc_wb_data_t *wb_data = (ctc_wb_data_t *)(data->data);
    uint8 lchip = (uint8)(data->value1);

    max_entry_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb_mcast_info = (sys_wb_stacking_mcast_db_t *)wb_data->buffer + wb_data->valid_cnt;

    CTC_ERROR_RETURN(_sys_usw_stacking_wb_mapping_mcast(lchip, p_wb_mcast_info, p_mcast_info, 1));
    if (++wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_stacking_wb_restore_mcast_func(uint8 lchip, sys_wb_stacking_mcast_db_t* p_wb_stacking_mcast)
{
    sys_stacking_mcast_db_t* p_sys_mcast = NULL;
    int32 ret = 0;
    sys_nh_param_dsmet_t dsmet;

    p_sys_mcast = mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_mcast_db_t));
    if (NULL == p_sys_mcast)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_sys_mcast, 0, sizeof(sys_stacking_mcast_db_t));

    ret = _sys_usw_stacking_wb_mapping_mcast(lchip, p_wb_stacking_mcast, p_sys_mcast, 0);
    if (ret)
    {
        mem_free(p_sys_mcast);
        return CTC_E_NO_MEMORY;
    }
    /*mcast profile alloc id*/
    if(p_sys_mcast->alloc_id)
    {
        sys_usw_opf_t  opf;
        sal_memset(&opf, 0, sizeof(opf));
        opf.pool_type  = g_stacking_master[lchip]->opf_type;
        opf.pool_index = SYS_STK_OPF_MCAST_PROFILE;
        sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1, p_sys_mcast->id);
    }

    /*mcast group or keep alive group alloc head node*/
    if(p_sys_mcast->type)
    {
        CTC_ERROR_GOTO(sys_usw_nh_set_glb_met_offset(lchip, p_sys_mcast->id, 1, TRUE), ret, error0);
    }
    else
    {
        CTC_ERROR_GOTO(sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_MET_RSVED, 1, p_sys_mcast->head_met_offset), ret, error0);
    }

    /*mcast group or keep alive group alloc middle node*/
    sys_usw_nh_get_dsmet(lchip, p_sys_mcast->head_met_offset, &dsmet);
    while(dsmet.next_met_entry_ptr != p_sys_mcast->last_tail_offset)
    {
        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_MET_RSVED, 1, dsmet.next_met_entry_ptr);
        sys_usw_nh_get_dsmet(lchip, dsmet.next_met_entry_ptr, &dsmet);
    }


    if(NULL == ctc_hash_insert(g_stacking_master[lchip]->mcast_hash, p_sys_mcast))
    {
        mem_free(p_sys_mcast);
        return CTC_E_NO_MEMORY;
    }
    if(p_sys_mcast->id == 0 && p_sys_mcast->type == 0)
    {
        g_stacking_master[lchip]->p_default_prof_db = p_sys_mcast;
    }

    return CTC_E_NONE;

error0:
    mem_free(p_sys_mcast);
    return ret;
}

int32
sys_usw_stacking_wb_sync(uint8 lchip, uint32 app_id)
{
    int32 ret  = CTC_E_NONE;
    ctc_wb_data_t wb_data ={0};
    sys_traverse_t user_data = {0};
    sys_wb_stacking_master_t* p_wb_stacking_master = NULL;
    uint16* temp_ptr = NULL;

    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    STACKING_LOCK;
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_STACKING_SUBID_MASTER)
    {
        /*Sync master*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_stacking_master_t, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER);
        p_wb_stacking_master = (sys_wb_stacking_master_t  *)wb_data.buffer;
        if (NULL == p_wb_stacking_master)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }

        p_wb_stacking_master->lchip = lchip;
        p_wb_stacking_master->stacking_mcast_offset = g_stacking_master[lchip]->stacking_mcast_offset;
        p_wb_stacking_master->binding_trunk = g_stacking_master[lchip]->binding_trunk;
        p_wb_stacking_master->bind_mcast_en = g_stacking_master[lchip]->bind_mcast_en;
        p_wb_stacking_master->version = SYS_WB_VERSION_STACKING;
        sal_memcpy(&p_wb_stacking_master->ing_port_en_bmp, &g_stacking_master[lchip]->ing_port_en_bmp, sizeof(ctc_port_bitmap_t));
        sal_memcpy(&p_wb_stacking_master->egr_port_en_bmp, &g_stacking_master[lchip]->egr_port_en_bmp, sizeof(ctc_port_bitmap_t));
        CTC_ERROR_GOTO(sys_usw_l2_wb_sync_rchip_rsv_ad(lchip, &temp_ptr), ret, done);
        sal_memcpy(p_wb_stacking_master->rchip_ad_rsv, temp_ptr, (SYS_USW_MAX_GCHIP_CHIP_ID+1)*sizeof(uint16));

        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_STACKING_SUBID_TRUNK)
    {
        /*Sync trunk*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_stacking_trunk_t, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_TRUNK);
        ctc_vector_traverse2(g_stacking_master[lchip]->p_trunk_vec, 0, _sys_usw_stacking_wb_traverse_sync_trunk_node, &wb_data);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_TRUNK);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_STACKING_SUBID_MCAST_DB)
    {
        /*Sync mcast_hash*/

        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_stacking_mcast_db_t, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB);
        user_data.data = &wb_data;
        user_data.value1 = lchip;
        user_data.value2 = 0;
        CTC_ERROR_GOTO(ctc_hash_traverse(g_stacking_master[lchip]->mcast_hash, (hash_traversal_fn) _sys_usw_stacking_wb_sync_mcast_func, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB);
    }

    done:
    STACKING_UNLOCK;
    CTC_WB_FREE_BUFFER(wb_data.buffer);

    return ret;
}

int32 sys_usw_stacking_wb_restore(uint8 lchip)
{
    int32 ret = 0;
    uint32 entry_cnt = 0;
    uint8 gchip = 0;
    uint32 chan_id = 0;
    uint16 lport = 0;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint32 tbl_id = DRV_FROM_AT(lchip)? UcQWritePortIsolationCtl_t :QWritePortIsolateCtl_t;
    uint8 hdr_len = 0xff;
    uint16 mem_base = 0;
    uint16 mem_cnt = 0;
    uint8 is_dlb = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    ctc_wb_query_t    wb_query;
    sys_stacking_trunk_info_t* p_sys_trunk = NULL;
    sys_wb_stacking_master_t   wb_stacking_master;
    sys_wb_stacking_master_t*  p_wb_stacking_master = &wb_stacking_master;
    sys_wb_stacking_trunk_t    wb_stacking_trunk;
    sys_wb_stacking_trunk_t*   p_wb_stacking_trunk = &wb_stacking_trunk;
    sys_wb_stacking_mcast_db_t  wb_stacking_mcast;
    sys_wb_stacking_mcast_db_t* p_wb_stacking_mcast = &wb_stacking_mcast;
    sys_usw_opf_t  opf;
    QWritePortIsolateCtl_m qwrite_table;
    uint16 *temp_ptr = NULL; 

    sys_usw_get_gchip_id(lchip, &gchip);
    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    /*Restore Master*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_stacking_master_t, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER);
    sal_memset(p_wb_stacking_master, 0, sizeof(sys_wb_stacking_master_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)p_wb_stacking_master, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;
        if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_STACKING, p_wb_stacking_master->version))
        {
            ret = CTC_E_VERSION_MISMATCH;
            goto done;
        }


        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &qwrite_table));
        if(g_stacking_master[lchip]->isolation_mode != GetQWritePortIsolateCtl(V, cFlexDstIsolateMode_f, &qwrite_table))
        {
            ret = CTC_E_VERSION_MISMATCH;
            goto done;
        }
        g_stacking_master[lchip]->stacking_mcast_offset = p_wb_stacking_master->stacking_mcast_offset;
        g_stacking_master[lchip]->binding_trunk = p_wb_stacking_master->binding_trunk;
        g_stacking_master[lchip]->bind_mcast_en = p_wb_stacking_master->bind_mcast_en;
        sal_memcpy(&g_stacking_master[lchip]->ing_port_en_bmp, &p_wb_stacking_master->ing_port_en_bmp, sizeof(ctc_port_bitmap_t));
        sal_memcpy(&g_stacking_master[lchip]->egr_port_en_bmp, &p_wb_stacking_master->egr_port_en_bmp, sizeof(ctc_port_bitmap_t));

        for (lport=0; lport<MCHIP_CAP(SYS_CAP_PORT_NUM); lport++)
        {
            hdr_len = 0xff;
            dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);
            CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id), ret, done);
            if (!SYS_IS_NETWORK_CHANNEL(chan_id))
            {
                continue;
            }
            cmd = DRV_IOR(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_cFlexLookupMode_f);
            DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val);
            sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_CFLEX_MODE, lport,  field_val);

            cmd = DRV_IOR(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_muxType_f);
            DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val);
            if (field_val == DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITHOUT_TUNNEL))
            {
                hdr_len = 0;
            }
            else if(field_val == DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2))
            {
                cmd = DRV_IOR(DsPacketHeaderEditTunnel_t, DsPacketHeaderEditTunnel_vlanIdValid_f);
                DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val);
                hdr_len = field_val?18:14;
            }
            sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_CLD_HDR_LEN, lport,  hdr_len);
        }
        temp_ptr = p_wb_stacking_master->rchip_ad_rsv;
        CTC_ERROR_GOTO(sys_usw_l2_wb_restore_rchip_rsv_ad(lchip, &temp_ptr), ret, done);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*Restore trunk*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_stacking_trunk_t, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_TRUNK);
    sal_memset(p_wb_stacking_trunk, 0, sizeof(sys_wb_stacking_trunk_t));

    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)p_wb_stacking_trunk, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        p_sys_trunk = (sys_stacking_trunk_info_t*)mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_trunk_info_t));
        if (NULL == p_sys_trunk)
        {
            ret =  CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_sys_trunk, 0, sizeof(sys_stacking_trunk_info_t));

        p_sys_trunk->trunk_id = p_wb_stacking_trunk->trunk_id;
        p_sys_trunk->max_mem_cnt = p_wb_stacking_trunk->max_mem_cnt;
        p_sys_trunk->flow_cnt = p_wb_stacking_trunk->flow_cnt;
        p_sys_trunk->replace_en = p_wb_stacking_trunk->replace_en;
        p_sys_trunk->mode = p_wb_stacking_trunk->mode;
        CTC_ERROR_RETURN(_sys_usw_stacking_get_trunk_info(lchip, p_sys_trunk->trunk_id, &mem_cnt, &mem_base, &is_dlb));
        if (0 != mem_cnt)
        {
            ds_t  hw_member;
            DsPacketHeaderEditTunnel_m pkt_edit_tunnel;
            uint32 cmd = 0;
            uint32 field_val = 0;
            uint32 hdr_flag = 0;
            hw_mac_addr_t mac;
            if (!is_dlb)
            {
                cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, mem_base, cmd, &hw_member));
                chan_id = GetDsLinkAggregateChannelMember(V, channelId_f, &hw_member);
            }
            else
            {
                cmd = DRV_IOR(DsLinkAggregateChannelMemberSet_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_sys_trunk->trunk_id, cmd, &hw_member));
                chan_id = GetDsLinkAggregateChannelMemberSet(V, array_0_channelId_f, &hw_member);
            }

            cmd = DRV_IOR(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_muxType_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, SYS_USW_CHANNEL_DECODE(chan_id), cmd, &field_val));
            if (DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITHOUT_TUNNEL) == field_val)
            {
                hdr_flag = CTC_STK_HDR_WITH_NONE;
            }
            else if (DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2) == field_val)
            {
                hdr_flag = CTC_STK_HDR_WITH_L2;
            }
            else if (DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2_AND_IPV4) == field_val)
            {
                hdr_flag = CTC_STK_HDR_WITH_L2_AND_IPV4;
            }
            else if (DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_L2_AND_IPV6) == field_val)
            {
                hdr_flag = CTC_STK_HDR_WITH_L2_AND_IPV6;
            }
            else if (DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_IPV4) == field_val)
            {
                hdr_flag = CTC_STK_HDR_WITH_IPV4;
            }
            else if (DRV_ENUM(DRV_STK_MUX_TYPE_HDR_WITH_IPV6) == field_val)
            {
                hdr_flag = CTC_STK_HDR_WITH_IPV6;
            }

            if (hdr_flag != CTC_STK_HDR_WITH_NONE)
            {
                p_sys_trunk->p_encap_hdr = (ctc_stacking_hdr_encap_t*)mem_malloc(MEM_STK_MODULE, sizeof(ctc_stacking_hdr_encap_t));
                if (NULL == p_sys_trunk->p_encap_hdr)
                {
                    mem_free(p_sys_trunk);
                    ret =  CTC_E_NO_MEMORY;
                    goto done;
                }
                sal_memset(p_sys_trunk->p_encap_hdr, 0, sizeof(ctc_stacking_hdr_encap_t));
                p_sys_trunk->p_encap_hdr->hdr_flag = hdr_flag;
                cmd = DRV_IOR(DsPacketHeaderEditTunnel_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, SYS_USW_CHANNEL_DECODE(chan_id), cmd, &pkt_edit_tunnel));
                p_sys_trunk->p_encap_hdr->vlan_valid = GetDsPacketHeaderEditTunnel(V, vlanIdValid_f, &pkt_edit_tunnel);
                p_sys_trunk->p_encap_hdr->vlan_id = GetDsPacketHeaderEditTunnel(V, vlanId_f, &pkt_edit_tunnel);
                GetDsPacketHeaderEditTunnel(A, macDa_f, &pkt_edit_tunnel, mac);
                SYS_USW_SET_USER_MAC(p_sys_trunk->p_encap_hdr->mac_da, mac);
                GetDsPacketHeaderEditTunnel(A, macSa_f , &pkt_edit_tunnel, mac);
                SYS_USW_SET_USER_MAC(p_sys_trunk->p_encap_hdr->mac_sa, mac);

                if (CTC_STK_HDR_WITH_L2_AND_IPV4 == hdr_flag || CTC_STK_HDR_WITH_IPV4 == hdr_flag)
                {
                    GetDsPacketHeaderEditTunnel(A, ipDa_f , &pkt_edit_tunnel, &p_sys_trunk->p_encap_hdr->ipda.ipv4);
                }
                if (CTC_STK_HDR_WITH_L2_AND_IPV6 == hdr_flag || CTC_STK_HDR_WITH_IPV6 == hdr_flag)
                {
                    uint32 v6_addr_hw[4];

                    GetDsPacketHeaderEditTunnel(A, ipDa_f, &pkt_edit_tunnel, &v6_addr_hw);
                    SYS_USW_REVERT_IP6(p_sys_trunk->p_encap_hdr->ipda.ipv6, v6_addr_hw);
                }
            }
        }

        p_sys_trunk->mem_base = mem_base;
        
        if (DRV_FROM_TMM(lchip) && p_sys_trunk->mode == CTC_STK_LOAD_DYNAMIC)
        {
            p_sys_trunk->flow_base = mem_base;
            CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset_from_position(lchip, DsLagDlbFlowSetTable_t, 0, p_sys_trunk->flow_cnt, p_sys_trunk->flow_base));
        }
        else if (p_sys_trunk->max_mem_cnt)
        {
            sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
            opf.pool_type  = g_stacking_master[lchip]->opf_type;
            opf.pool_index = SYS_STK_OPF_MEM_BASE;
            CTC_ERROR_RETURN(sys_usw_opf_alloc_offset_from_position(lchip, &opf, p_sys_trunk->max_mem_cnt, p_sys_trunk->mem_base));
        }
        ctc_vector_add(g_stacking_master[lchip]->p_trunk_vec,  p_sys_trunk->trunk_id, p_sys_trunk);

    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*Restore  mcast*/
    CTC_WB_INIT_QUERY_T((&wb_query),sys_wb_stacking_mcast_db_t, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB);
    sal_memset(p_wb_stacking_mcast, 0, sizeof(sys_wb_stacking_mcast_db_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)p_wb_stacking_mcast, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;
        CTC_ERROR_GOTO(_sys_usw_stacking_wb_restore_mcast_func(lchip, p_wb_stacking_mcast), ret, done);
    CTC_WB_QUERY_ENTRY_END((&wb_query));


   /********************************
   Restore from hardware
   **********************************/
   CTC_ERROR_GOTO(_sys_usw_stacking_wb_restore_block_profile(lchip), ret, done);
   CTC_ERROR_GOTO(_sys_usw_stacking_wb_restore_fwd_profile(lchip), ret, done);
   CTC_ERROR_GOTO(_sys_usw_stacking_wb_restore_glb_port(lchip), ret, done);


done:
   CTC_WB_FREE_BUFFER(wb_query.buffer);

   return ret;
}

STATIC int32
_sys_usw_stacking_wb_init(uint8 lchip)
{
    ctc_wb_appid_t  appid;
    sal_memset(&appid, 0, sizeof(appid));

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MASTER) ;
    appid.entry_num = 1;
    appid.entry_size  = sizeof(sys_wb_stacking_master_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_TRUNK) ;
    appid.entry_num = MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_NUM);
    appid.entry_size  = sizeof(sys_wb_stacking_trunk_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MCAST_DB) ;
    appid.entry_num = SYS_WB_STACKING_SUBID_MCAST_DB_NUM;
    appid.entry_size  = sizeof(sys_wb_stacking_mcast_db_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    return CTC_E_NONE;
}


#define ______INIT______

int32
sys_usw_stacking_init(uint8 lchip, void* p_cfg)
{
    int32 ret                      = CTC_E_NONE;
    ctc_spool_t spool;
	sys_usw_opf_t opf;
    ctc_stacking_glb_cfg_t* p_glb_cfg = (ctc_stacking_glb_cfg_t*)p_cfg;
    uint8 chip_shift;
    uint8 profile_shift;
    uint8 profile_num;
    uint16 index = 0;
    uint32 chan_id = 0;
    uint16 max_chan = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    if (g_stacking_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, g_stacking_master, CTC_FEATURE_STACKING);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->trunk_mode, CTC_STACKING_TRUNK_MODE_MAX - 1);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->version, CTC_STACKING_VERSION_2_0);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->learning_mode, CTC_STK_LEARNING_MODE_NONE);

    g_stacking_master[lchip] = (sys_stacking_master_t*)mem_malloc(MEM_STK_MODULE, sizeof(sys_stacking_master_t));
    if (NULL == g_stacking_master[lchip])
    {
        ret = CTC_E_NO_MEMORY;
        goto ERROR_FREE_MEM;
    }
    sal_memset(g_stacking_master[lchip], 0, sizeof(sys_stacking_master_t));

    g_stacking_master[lchip]->p_trunk_vec = ctc_vector_init(SYS_STK_TRUNK_VEC_BLOCK_NUM, SYS_STK_TRUNK_VEC_BLOCK_SIZE);
    if (NULL == g_stacking_master[lchip]->p_trunk_vec)
    {
        ret = CTC_E_NO_MEMORY;
        goto ERROR_FREE_MEM;
    }

    g_stacking_master[lchip]->mcast_hash  = ctc_hash_create(
            (SYS_STK_MCAST_PROFILE_MAX/CTC_HASH_16_BLOCK_SIZE),
            CTC_HASH_16_BLOCK_SIZE,
            (hash_key_fn)_sys_usw_stacking_mcast_hash_make,
            (hash_cmp_fn)_sys_usw_stacking_mcast_hash_cmp);
    if (NULL == g_stacking_master[lchip]->mcast_hash)
    {
        ret = CTC_E_NO_MEMORY;
        goto ERROR_FREE_MEM;
    }

    /* set register cb api */
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_STK_GET_STKHDR_VER, sys_usw_stacking_get_stkhdr_ver), ret, ERROR_FREE_MEM);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_STK_GET_RSV_TRUNK_NUM, sys_usw_stacking_get_rsv_trunk_number), ret, ERROR_FREE_MEM);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_STK_GET_MCAST_PROFILE_MET_OFFSET, sys_usw_stacking_get_mcast_profile_met_offset), ret, ERROR_FREE_MEM);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_STK_GET_BINDING_TRUNK, sys_usw_stacking_get_binding_trunk), ret, ERROR_FREE_MEM);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_STK_GET_TRUNK_BY_RCHIP, sys_usw_stacking_get_trunk_by_rchip), ret, ERROR_FREE_MEM);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_STK_GET_VERSION, sys_usw_stacking_get_version), ret, ERROR_FREE_MEM);

    /*init opf*/
    ret = sys_usw_opf_init(lchip, &g_stacking_master[lchip]->opf_type, SYS_STK_OPF_MAX, "opf-stacking-profile");
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

	sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
	opf.pool_type  = g_stacking_master[lchip]->opf_type;
	opf.pool_index = SYS_STK_OPF_MEM_BASE;
	ret = sys_usw_opf_init_offset(lchip, &opf, 0 , MCHIP_CAP(SYS_CAP_STK_TRUNK_MEMBERS));
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

    /*0 is compitible mode, support 128 chips + 64 chan before TM.MX but 128 chips + 128 chan from TM.MX.
      If the configured value exceeds the maximum capacity of the chip,
                    it will be processed according to the maximum capacity of the chip*/
    g_stacking_master[lchip]->max_gchip_id = (0 == p_glb_cfg->max_gchip_id || p_glb_cfg->max_gchip_id >= MCHIP_CAP(SYS_CAP_SPEC_MAX_CHIP_NUM)) ?
        MCHIP_CAP(SYS_CAP_SPEC_MAX_CHIP_NUM)-1 : p_glb_cfg->max_gchip_id;
    g_stacking_master[lchip]->max_block_port_id = (0 == p_glb_cfg->max_block_port_id) ? ((DRV_FROM_TMM(lchip)) ? 127:63):\
                                     (p_glb_cfg->max_block_port_id >= MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)) ? \
                                     (MCHIP_CAP(SYS_CAP_SPEC_MAX_PORT_NUM)-1) : p_glb_cfg->max_block_port_id;

    for (index = 0; index < g_stacking_master[lchip]->max_block_port_id; index++)
    {
        dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(lchip, index);
        CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id), ret, ERROR_FREE_MEM);

        if (SYS_COMMON_USELESS_CHANNEL == chan_id)
        {
            continue;
        }
        if ((chan_id > g_stacking_master[lchip]->max_block_port_id) && (chan_id > max_chan))
        {
            max_chan = chan_id;
        }
    }

    /*remote block function use dest channel as egress port id, not lport, so need adjust max_block_port_id according channel id*/
    g_stacking_master[lchip]->max_block_port_id = (max_chan > g_stacking_master[lchip]->max_block_port_id)?max_chan:g_stacking_master[lchip]->max_block_port_id;

    if(DRV_FROM_TMM(lchip))
    {
        g_stacking_master[lchip]->isolation_mode = (g_stacking_master[lchip]->max_gchip_id >= 64) ? ((g_stacking_master[lchip]->max_block_port_id < 128) ? 1 : 3 ):2;
    }
    else
    {
        if(g_stacking_master[lchip]->max_gchip_id >= 64)
        {
            g_stacking_master[lchip]->isolation_mode = (g_stacking_master[lchip]->max_block_port_id < 64) ? 1 : (g_stacking_master[lchip]->max_block_port_id < 128) ? 2 : 3;
        }
        else
        {
            g_stacking_master[lchip]->isolation_mode = (g_stacking_master[lchip]->max_block_port_id < 128) ? 4 : 5;
        }
    }
    _sys_usw_stacking_get_isolation_info(lchip, &chip_shift, &profile_shift, &profile_num);
	opf.pool_index = SYS_STK_OPF_BLOCK;
	ret = sys_usw_opf_init_offset(lchip, &opf, 1 , profile_num-1);
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

	opf.pool_index = SYS_STK_OPF_FWD;
    ret = sys_usw_opf_init_offset(lchip, &opf, 1 , SYS_STK_PORT_FWD_PROFILE_NUM-1);
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

    /*0 ~ 255 is reserved for local chip*/
	opf.pool_index = SYS_STK_OPF_ABILITY;
    ret = sys_usw_opf_init_offset(lchip, &opf, MCHIP_CAP(SYS_CAP_RSV_PORT_START), MCHIP_CAP(SYS_CAP_STK_GLB_DEST_PORT_NUM)-MCHIP_CAP(SYS_CAP_RSV_PORT_START));
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

    opf.pool_index = SYS_STK_OPF_MCAST_PROFILE;
    ret = sys_usw_opf_init_offset(lchip, &opf, 1 , (SYS_STK_MCAST_PROFILE_MAX-1));
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

    /*init block profile*/
    sal_memset(&spool, 0, sizeof(ctc_spool_t));
    spool.lchip = lchip;
    spool.block_num = 1;
    spool.block_size = SYS_STK_PORT_BLOCK_PROFILE_NUM;
    spool.max_count = SYS_STK_PORT_BLOCK_PROFILE_NUM;
    //spool.user_data_size = CTC_OFFSET_OF(sys_stacking_block_profile_t, calc_key_len);
    spool.user_data_size = sizeof(sys_stacking_block_profile_t);
    spool.spool_key = (hash_key_fn)_sys_usw_stacking_block_profile_hash_make;
    spool.spool_cmp = (hash_cmp_fn)_sys_usw_stacking_block_profile_hash_compare;
    spool.spool_alloc = (spool_alloc_fn)_sys_usw_stacking_block_profile_index_alloc;
    spool.spool_free= (spool_free_fn)_sys_usw_stacking_block_profile_index_free;
    g_stacking_master[lchip]->p_block_prof_spool = ctc_spool_create(&spool);
    ret = _sys_usw_stacking_add_static_block_port_profile(lchip);
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }
    /*init fwd profile*/
    sal_memset(&spool, 0, sizeof(ctc_spool_t));
    spool.lchip = lchip;
    spool.block_num = 1;
    spool.block_size = SYS_STK_PORT_FWD_PROFILE_NUM;
    spool.max_count = SYS_STK_PORT_FWD_PROFILE_NUM;
    //spool.user_data_size = CTC_OFFSET_OF(sys_stacking_fwd_profile_t, calc_key_len);
    spool.user_data_size = sizeof(sys_stacking_fwd_profile_t);
    spool.spool_key = (hash_key_fn)_sys_usw_stacking_fwd_profile_hash_make;
    spool.spool_cmp = (hash_cmp_fn)_sys_usw_stacking_fwd_profile_hash_compare;
    spool.spool_alloc = (spool_alloc_fn)_sys_usw_stacking_fwd_profile_index_alloc;
    spool.spool_free= (spool_free_fn)_sys_usw_stacking_fwd_profile_index_free;
    g_stacking_master[lchip]->p_fwd_prof_spool = ctc_spool_create(&spool);
    ret = _sys_usw_stacking_add_static_fwd_port_profile(lchip);
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

    g_stacking_master[lchip]->stacking_ver = p_glb_cfg->version;
    /*default mcast group & keeplive group restore from database*/
    if(!( CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING) )
    {

        ret =  _sys_usw_stacking_mcast_group_create(lchip, 0, 0, &g_stacking_master[lchip]->p_default_prof_db, 0);
        if (NULL == g_stacking_master[lchip]->p_default_prof_db)
        {
            goto ERROR_FREE_MEM;
        }
        g_stacking_master[lchip]->stacking_mcast_offset = g_stacking_master[lchip]->p_default_prof_db->head_met_offset;

        ret = sys_usw_stacking_create_keeplive_group(lchip, 0);
        if (CTC_E_NONE != ret)
        {
            goto ERROR_FREE_MEM;
        }

    }
    ret = _sys_usw_stacking_hdr_set(lchip, &p_glb_cfg->hdr_glb);
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

    ret = _sys_usw_stacking_register_en(lchip, p_glb_cfg);
    if (CTC_E_NONE != ret)
    {
        goto ERROR_FREE_MEM;
    }

    ret = sal_mutex_create(&(g_stacking_master[lchip]->p_stacking_mutex));
    if (ret || !(g_stacking_master[lchip]->p_stacking_mutex))
    {
        goto ERROR_FREE_MEM;
    }

    g_stacking_master[lchip]->fabric_mode = p_glb_cfg->fabric_mode?1:0;
    g_stacking_master[lchip]->trunk_mode = p_glb_cfg->trunk_mode;
    g_stacking_master[lchip]->mcast_mode = p_glb_cfg->mcast_mode?1:0;
    g_stacking_master[lchip]->bind_mcast_en = 0;
    g_stacking_master[lchip]->src_port_mode = p_glb_cfg->src_port_mode;
    CTC_ERROR_RETURN(sys_usw_port_api_register_rchip_get_gport_idx_cb(lchip, _sys_usw_stacking_map_gport));

    if(CTC_STACKING_VERSION_2_0 == p_glb_cfg->version)
    {
        uint8  gchip;
        uint16 lport;
        DsGlbDestPortMap_m glb_dest_port_map;
        uint32 cmd = DRV_IOW(DsGlbDestPortMap_t, DRV_ENTRY_FLAG);
        sal_memset(&glb_dest_port_map, 0, sizeof(glb_dest_port_map));
        SetDsGlbDestPortMap(V, glbDestPortBase_f, &glb_dest_port_map, 0);
        SetDsGlbDestPortMap(V, glbDestPortMin_f, &glb_dest_port_map, 0);
        SetDsGlbDestPortMap(V, glbDestPortMax_f, &glb_dest_port_map, MCHIP_CAP(SYS_CAP_RSV_PORT_START));

        CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, gchip, cmd, &glb_dest_port_map));

         /*reinit port for stacking version 2.0 need config global dest port*/
        for(lport=0; lport < MCHIP_CAP(SYS_CAP_RSV_PORT_START); lport++)
        {
            sys_usw_port_api_set_glb_dest_port_by_dest_port(lchip, lport);
        }

    }

    ret = _sys_usw_stacking_set_trunk_mode(lchip, g_stacking_master[lchip]->trunk_mode);
    if (ret)
    {
        goto ERROR_FREE_MEM;
    }

    /*warm boot*/
    CTC_ERROR_RETURN(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_STACKING, SYS_WB_APPID_STACKING_SUBID_MAX,sys_usw_stacking_wb_sync));

    if( CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_RETURN(sys_usw_stacking_wb_restore(lchip));
    }
    if (CTC_WB_ENABLE(lchip))
    {
        CTC_ERROR_RETURN(_sys_usw_stacking_wb_init(lchip));
    }

    /* dump-db register */
    CTC_ERROR_RETURN(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_STACKING, sys_usw_stacking_dump_db));
    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_STACKING);
    return CTC_E_NONE;

ERROR_FREE_MEM:


    if (g_stacking_master[lchip]->stacking_mcast_offset)
    {
        sys_usw_nh_free(lchip, SYS_API_NH_DSMET_RSVED, 1, g_stacking_master[lchip]->stacking_mcast_offset);
    }

    if (g_stacking_master[lchip]->p_stacking_mutex)
    {
        sal_mutex_destroy(g_stacking_master[lchip]->p_stacking_mutex);
    }

    if (NULL != g_stacking_master[lchip])
    {
        mem_free(g_stacking_master[lchip]);
    }

    return ret;
}

STATIC int32
_sys_usw_stacking_free_node_data(void* node_data, void* user_data)
{
    mem_free(node_data);

    return CTC_E_NONE;
}

int32
sys_usw_stacking_deinit(uint8 lchip)
{
    LCHIP_CHECK(lchip);

    if (NULL == g_stacking_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, g_stacking_master, CTC_FEATURE_STACKING);
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_STACKING, 0,NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_STACKING, NULL);

    /*free trunk vector*/
    ctc_vector_traverse(g_stacking_master[lchip]->p_trunk_vec, (vector_traversal_fn)_sys_usw_stacking_free_node_data, NULL);
    ctc_vector_release(g_stacking_master[lchip]->p_trunk_vec);

    ctc_hash_free2(g_stacking_master[lchip]->mcast_hash, (hash_traversal_fn)_sys_usw_stacking_free_node_data, NULL);

    /*free spool data*/
    ctc_spool_free(g_stacking_master[lchip]->p_block_prof_spool);
    ctc_spool_free(g_stacking_master[lchip]->p_fwd_prof_spool);

    sys_usw_opf_deinit(lchip, g_stacking_master[lchip]->opf_type);

    sal_mutex_destroy(g_stacking_master[lchip]->p_stacking_mutex);
    mem_free(g_stacking_master[lchip]);

    return CTC_E_NONE;

}

#endif

